From 52a9f1f2a364fb3de530d195059f0cbcd2c05b64 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Fri, 6 Jan 2006 20:33:41 +0100 Subject: [PATCH] --- yaml --- r: 16655 b: refs/heads/master c: 253dfa6e465c054a73bd3b13af51c34c9d8d233d h: refs/heads/master i: 16653: 292a27645328722eeef7ef3b1ef00cafa56185bc 16651: b451090d42778318f9237da9104a2b5826530718 16647: a11160e7e94e9a3426636a09c1f1665e03b90050 16639: 2936ac8872b48c45416818f0edd445970e904277 v: v3 --- [refs] | 2 +- trunk/Documentation/block/biodoc.txt | 10 +- trunk/Documentation/kbuild/modules.txt | 40 + trunk/Documentation/kernel-parameters.txt | 8 - trunk/Documentation/keys.txt | 18 + trunk/Documentation/md.txt | 120 - trunk/Documentation/power/interface.txt | 11 - trunk/Documentation/power/swsusp.txt | 5 - trunk/MAINTAINERS | 14 +- trunk/arch/alpha/Kconfig | 13 - trunk/arch/alpha/kernel/alpha_ksyms.c | 1 + trunk/arch/alpha/kernel/irq.c | 630 +++++- trunk/arch/cris/arch-v10/kernel/kgdb.c | 6 + trunk/arch/frv/kernel/Makefile | 1 - trunk/arch/frv/kernel/entry.S | 2 +- trunk/arch/frv/kernel/futex.c | 242 -- trunk/arch/frv/kernel/signal.c | 155 +- trunk/arch/i386/Kconfig | 8 +- trunk/arch/i386/Kconfig.cpu | 14 +- trunk/arch/i386/Kconfig.debug | 10 - trunk/arch/i386/kernel/apic.c | 2 +- trunk/arch/i386/kernel/apm.c | 97 +- trunk/arch/i386/kernel/cpu/amd.c | 7 +- trunk/arch/i386/kernel/cpu/common.c | 8 + trunk/arch/i386/kernel/cpu/cyrix.c | 27 +- trunk/arch/i386/kernel/cpuid.c | 3 +- trunk/arch/i386/kernel/entry.S | 1 - trunk/arch/i386/kernel/head.S | 27 +- trunk/arch/i386/kernel/i386_ksyms.c | 3 +- trunk/arch/i386/kernel/io_apic.c | 4 +- trunk/arch/i386/kernel/mpparse.c | 26 +- trunk/arch/i386/kernel/msr.c | 3 +- trunk/arch/i386/kernel/process.c | 16 +- trunk/arch/i386/kernel/reboot.c | 6 +- trunk/arch/i386/kernel/setup.c | 8 - trunk/arch/i386/kernel/smpboot.c | 6 - trunk/arch/i386/kernel/syscall_table.S | 1 + trunk/arch/i386/kernel/timers/timer_tsc.c | 2 - trunk/arch/i386/kernel/traps.c | 33 +- trunk/arch/i386/mm/init.c | 24 - trunk/arch/i386/mm/pageattr.c | 27 +- trunk/arch/i386/pci/irq.c | 2 +- trunk/arch/m32r/Kconfig | 26 +- trunk/arch/m32r/boot/compressed/head.S | 5 - trunk/arch/m32r/boot/setup.S | 24 +- trunk/arch/m32r/kernel/Makefile | 1 - trunk/arch/m32r/kernel/entry.S | 19 +- trunk/arch/m32r/kernel/io_m32104ut.c | 298 --- trunk/arch/m32r/kernel/io_m32700ut.c | 24 +- trunk/arch/m32r/kernel/io_mappi.c | 2 +- trunk/arch/m32r/kernel/io_mappi2.c | 24 +- trunk/arch/m32r/kernel/io_mappi3.c | 51 +- trunk/arch/m32r/kernel/io_oaks32r.c | 2 +- trunk/arch/m32r/kernel/io_opsput.c | 6 +- trunk/arch/m32r/kernel/setup.c | 7 +- trunk/arch/m32r/kernel/setup_m32104ut.c | 156 -- trunk/arch/m32r/kernel/setup_m32700ut.c | 8 + trunk/arch/m32r/kernel/setup_mappi.c | 6 + trunk/arch/m32r/kernel/setup_mappi2.c | 6 + trunk/arch/m32r/kernel/setup_mappi3.c | 6 + trunk/arch/m32r/kernel/setup_oaks32r.c | 6 + trunk/arch/m32r/kernel/setup_opsput.c | 8 + trunk/arch/m32r/kernel/setup_usrv.c | 6 + trunk/arch/m32r/kernel/time.c | 4 +- trunk/arch/m32r/m32104ut/defconfig.m32104ut | 657 ------ trunk/arch/m32r/mm/cache.c | 36 +- trunk/arch/m68knommu/kernel/m68k_ksyms.c | 2 + trunk/arch/m68knommu/kernel/setup.c | 2 + trunk/arch/ppc/boot/simple/Makefile | 2 - trunk/arch/ppc/kernel/idle.c | 4 +- trunk/arch/ppc/platforms/4xx/ibm440gx.c | 2 + trunk/arch/ppc/platforms/4xx/ibm440sp.c | 1 + trunk/arch/ppc/platforms/lite5200.c | 2 - trunk/arch/ppc/platforms/mpc5200.c | 53 + trunk/arch/ppc/syslib/mpc52xx_pci.c | 95 +- trunk/arch/ppc/syslib/mpc52xx_setup.c | 6 +- trunk/arch/s390/Kconfig | 34 +- trunk/arch/s390/Makefile | 6 +- trunk/arch/s390/appldata/appldata_base.c | 8 +- trunk/arch/s390/appldata/appldata_os.c | 14 +- trunk/arch/s390/crypto/Makefile | 8 +- trunk/arch/s390/crypto/aes_s390.c | 248 --- trunk/arch/s390/crypto/crypt_s390_query.c | 129 -- .../crypto/{crypt_s390.h => crypt_z990.h} | 267 ++- trunk/arch/s390/crypto/crypt_z990_query.c | 111 + .../s390/crypto/{des_s390.c => des_z990.c} | 54 +- .../s390/crypto/{sha1_s390.c => sha1_z990.c} | 32 +- trunk/arch/s390/crypto/sha256_s390.c | 151 -- trunk/arch/s390/defconfig | 65 +- trunk/arch/s390/kernel/Makefile | 15 +- trunk/arch/s390/kernel/compat_linux.c | 2 +- trunk/arch/s390/kernel/compat_signal.c | 2 + trunk/arch/s390/kernel/cpcmd.c | 16 +- trunk/arch/s390/kernel/entry64.S | 18 +- trunk/arch/s390/kernel/head.S | 4 +- trunk/arch/s390/kernel/machine_kexec.c | 2 +- trunk/arch/s390/kernel/module.c | 12 +- trunk/arch/s390/kernel/process.c | 12 +- trunk/arch/s390/kernel/ptrace.c | 24 +- trunk/arch/s390/kernel/reipl_diag.c | 2 +- trunk/arch/s390/kernel/setup.c | 14 +- trunk/arch/s390/kernel/signal.c | 8 +- trunk/arch/s390/kernel/smp.c | 14 +- trunk/arch/s390/kernel/sys_s390.c | 12 +- trunk/arch/s390/kernel/traps.c | 10 +- trunk/arch/s390/kernel/vmlinux.lds.S | 2 +- trunk/arch/s390/lib/Makefile | 5 +- trunk/arch/s390/lib/spinlock.c | 2 +- trunk/arch/s390/mm/extmem.c | 2 +- trunk/arch/s390/mm/fault.c | 18 +- trunk/arch/s390/mm/init.c | 8 +- trunk/arch/s390/mm/mmap.c | 2 +- trunk/arch/s390/oprofile/Makefile | 2 +- trunk/arch/s390/oprofile/backtrace.c | 79 - trunk/arch/s390/oprofile/init.c | 4 - trunk/arch/um/drivers/chan_kern.c | 273 +-- trunk/arch/um/drivers/line.c | 298 ++- trunk/arch/um/drivers/mconsole_kern.c | 232 +- trunk/arch/um/drivers/mconsole_user.c | 12 +- trunk/arch/um/drivers/net_kern.c | 8 +- trunk/arch/um/drivers/ssl.c | 47 +- trunk/arch/um/drivers/stdio_console.c | 33 +- trunk/arch/um/drivers/ubd_kern.c | 15 +- trunk/arch/um/include/chan_kern.h | 25 +- trunk/arch/um/include/choose-mode.h | 3 - trunk/arch/um/include/irq_user.h | 13 +- trunk/arch/um/include/kern.h | 13 +- trunk/arch/um/include/line.h | 37 +- trunk/arch/um/include/mconsole.h | 8 +- trunk/arch/um/include/os.h | 17 +- trunk/arch/um/include/user_util.h | 1 + trunk/arch/um/kernel/Makefile | 6 +- trunk/arch/um/kernel/irq_user.c | 48 +- trunk/arch/um/kernel/process_kern.c | 4 + trunk/arch/um/kernel/sigio_user.c | 2 - trunk/arch/um/kernel/um_arch.c | 4 +- trunk/arch/um/kernel/umid.c | 323 ++- trunk/arch/um/os-Linux/Makefile | 4 +- trunk/arch/um/os-Linux/aio.c | 467 ++-- trunk/arch/um/os-Linux/umid.c | 335 --- trunk/arch/x86_64/Kconfig.debug | 10 - trunk/arch/x86_64/ia32/ia32entry.S | 2 +- trunk/arch/x86_64/kernel/process.c | 5 +- trunk/arch/x86_64/kernel/syscall.c | 2 +- trunk/arch/x86_64/mm/init.c | 23 - trunk/arch/x86_64/mm/pageattr.c | 9 +- trunk/block/Kconfig | 2 +- trunk/block/as-iosched.c | 144 +- trunk/block/cfq-iosched.c | 16 +- trunk/block/deadline-iosched.c | 8 +- trunk/block/elevator.c | 86 +- trunk/block/ll_rw_blk.c | 536 ++--- trunk/block/scsi_ioctl.c | 2 +- trunk/crypto/Kconfig | 43 +- trunk/crypto/tcrypt.c | 4 - trunk/crypto/tcrypt.h | 64 - trunk/drivers/base/memory.c | 7 +- trunk/drivers/block/DAC960.c | 2 +- trunk/drivers/block/Kconfig | 2 +- trunk/drivers/block/cciss.c | 2 +- trunk/drivers/block/cpqarray.c | 2 +- trunk/drivers/block/floppy.c | 2 +- trunk/drivers/block/nbd.c | 124 +- trunk/drivers/block/paride/Kconfig | 5 +- trunk/drivers/block/sx8.c | 2 +- trunk/drivers/block/ub.c | 2 +- trunk/drivers/block/viodasd.c | 2 +- trunk/drivers/cdrom/cdu31a.c | 2 +- trunk/drivers/char/Kconfig | 2 +- trunk/drivers/char/hangcheck-timer.c | 2 +- trunk/drivers/char/hw_random.c | 70 +- trunk/drivers/char/ipmi/ipmi_msghandler.c | 4 +- trunk/drivers/char/mmtimer.c | 90 +- trunk/drivers/char/watchdog/Kconfig | 2 +- trunk/drivers/ide/ide-cd.c | 4 +- trunk/drivers/ide/ide-disk.c | 137 +- trunk/drivers/ide/ide-io.c | 11 +- trunk/drivers/ieee1394/ieee1394_core.c | 4 +- trunk/drivers/input/evdev.c | 2 +- trunk/drivers/macintosh/therm_adt746x.c | 39 +- trunk/drivers/macintosh/therm_pm72.c | 7 +- .../drivers/macintosh/windfarm_lm75_sensor.c | 7 +- trunk/drivers/md/bitmap.c | 114 +- trunk/drivers/md/dm-crypt.c | 5 - trunk/drivers/md/dm-io.h | 3 + trunk/drivers/md/dm-ioctl.c | 21 +- trunk/drivers/md/dm-log.c | 2 +- trunk/drivers/md/dm-raid1.c | 13 +- trunk/drivers/md/dm-snap.c | 25 +- trunk/drivers/md/dm.c | 95 +- trunk/drivers/md/dm.h | 5 +- trunk/drivers/md/faulty.c | 9 +- trunk/drivers/md/kcopyd.c | 3 +- trunk/drivers/md/linear.c | 14 +- trunk/drivers/md/md.c | 893 ++------ trunk/drivers/md/multipath.c | 22 +- trunk/drivers/md/raid0.c | 26 +- trunk/drivers/md/raid1.c | 726 ++---- trunk/drivers/md/raid10.c | 544 ++--- trunk/drivers/md/raid5.c | 174 +- trunk/drivers/md/raid6main.c | 348 ++- trunk/drivers/media/video/cpia_pp.c | 30 +- trunk/drivers/message/i2o/Kconfig | 12 - trunk/drivers/message/i2o/bus-osm.c | 23 +- trunk/drivers/message/i2o/config-osm.c | 2 +- trunk/drivers/message/i2o/core.h | 20 +- trunk/drivers/message/i2o/device.c | 339 +-- trunk/drivers/message/i2o/driver.c | 12 +- trunk/drivers/message/i2o/exec-osm.c | 114 +- trunk/drivers/message/i2o/i2o_block.c | 190 +- trunk/drivers/message/i2o/i2o_config.c | 196 +- trunk/drivers/message/i2o/i2o_lan.h | 38 +- trunk/drivers/message/i2o/i2o_proc.c | 2 +- trunk/drivers/message/i2o/i2o_scsi.c | 89 +- trunk/drivers/message/i2o/iop.c | 356 +-- trunk/drivers/message/i2o/pci.c | 7 +- trunk/drivers/mmc/mmc_block.c | 4 +- trunk/drivers/net/phy/Kconfig | 2 +- trunk/drivers/net/plip.c | 2 + trunk/drivers/parport/Kconfig | 2 +- trunk/drivers/parport/daisy.c | 51 +- trunk/drivers/parport/ieee1284_ops.c | 62 +- trunk/drivers/parport/parport_pc.c | 30 +- trunk/drivers/parport/probe.c | 199 +- trunk/drivers/parport/share.c | 1 - trunk/drivers/pnp/pnpbios/bioscalls.c | 45 +- trunk/drivers/s390/Makefile | 2 +- trunk/drivers/s390/block/Kconfig | 8 +- trunk/drivers/s390/block/dasd.c | 34 +- trunk/drivers/s390/block/dasd_diag.c | 11 +- trunk/drivers/s390/block/dasd_diag.h | 31 +- trunk/drivers/s390/block/dasd_eckd.c | 9 +- trunk/drivers/s390/block/dasd_fba.c | 6 +- trunk/drivers/s390/block/dasd_int.h | 3 +- trunk/drivers/s390/block/dasd_ioctl.c | 5 +- trunk/drivers/s390/block/dcssblk.c | 2 +- trunk/drivers/s390/block/xpram.c | 4 +- trunk/drivers/s390/char/sclp_cpi.c | 2 +- trunk/drivers/s390/char/sclp_quiesce.c | 2 +- trunk/drivers/s390/char/tape_block.c | 4 +- trunk/drivers/s390/char/vmwatchdog.c | 2 +- trunk/drivers/s390/cio/blacklist.c | 234 +- trunk/drivers/s390/cio/blacklist.h | 2 +- trunk/drivers/s390/cio/ccwgroup.c | 6 +- trunk/drivers/s390/cio/chsc.c | 473 ++-- trunk/drivers/s390/cio/chsc.h | 13 +- trunk/drivers/s390/cio/cio.c | 168 +- trunk/drivers/s390/cio/cio.h | 11 +- trunk/drivers/s390/cio/cmf.c | 8 +- trunk/drivers/s390/cio/css.c | 297 ++- trunk/drivers/s390/cio/css.h | 43 +- trunk/drivers/s390/cio/device.c | 47 +- trunk/drivers/s390/cio/device.h | 1 - trunk/drivers/s390/cio/device_fsm.c | 29 +- trunk/drivers/s390/cio/device_id.c | 26 +- trunk/drivers/s390/cio/device_ops.c | 4 +- trunk/drivers/s390/cio/device_pgid.c | 56 +- trunk/drivers/s390/cio/device_status.c | 14 +- trunk/drivers/s390/cio/ioasm.h | 86 +- trunk/drivers/s390/cio/qdio.c | 713 ++---- trunk/drivers/s390/cio/qdio.h | 144 +- trunk/drivers/s390/cio/schid.h | 26 - trunk/drivers/s390/crypto/z90common.h | 9 +- trunk/drivers/s390/crypto/z90crypt.h | 13 +- trunk/drivers/s390/crypto/z90hardware.c | 309 +-- trunk/drivers/s390/crypto/z90main.c | 111 +- trunk/drivers/s390/net/Kconfig | 2 +- trunk/drivers/s390/net/claw.c | 6 +- trunk/drivers/s390/net/cu3088.c | 3 +- trunk/drivers/s390/net/iucv.c | 10 +- trunk/drivers/s390/net/qeth_main.c | 21 +- trunk/drivers/s390/s390_rdev.c | 53 - trunk/drivers/s390/s390mach.c | 66 +- trunk/drivers/s390/sysinfo.c | 2 +- trunk/drivers/scsi/Kconfig | 10 +- trunk/drivers/scsi/ahci.c | 1 + trunk/drivers/scsi/ata_piix.c | 5 +- trunk/drivers/scsi/hosts.c | 9 + trunk/drivers/scsi/ide-scsi.c | 4 +- trunk/drivers/scsi/libata-core.c | 145 +- trunk/drivers/scsi/libata-scsi.c | 48 +- trunk/drivers/scsi/libata.h | 4 +- trunk/drivers/scsi/sata_mv.c | 1 + trunk/drivers/scsi/sata_nv.c | 1 + trunk/drivers/scsi/sata_promise.c | 1 + trunk/drivers/scsi/sata_sil.c | 1 + trunk/drivers/scsi/sata_sil24.c | 1 + trunk/drivers/scsi/sata_sis.c | 1 + trunk/drivers/scsi/sata_svw.c | 1 + trunk/drivers/scsi/sata_sx4.c | 1 + trunk/drivers/scsi/sata_uli.c | 1 + trunk/drivers/scsi/sata_via.c | 1 + trunk/drivers/scsi/sata_vsc.c | 1 + trunk/drivers/scsi/scsi_lib.c | 50 +- trunk/drivers/scsi/scsi_sysfs.c | 31 - trunk/drivers/scsi/sd.c | 85 +- trunk/drivers/serial/mpc52xx_uart.c | 28 +- trunk/fs/bio.c | 26 +- trunk/fs/exec.c | 2 +- trunk/fs/fuse/dev.c | 72 +- trunk/fs/fuse/dir.c | 278 +-- trunk/fs/fuse/file.c | 49 +- trunk/fs/fuse/fuse_i.h | 12 +- trunk/fs/fuse/inode.c | 14 +- trunk/fs/hfsplus/super.c | 2 +- trunk/fs/hugetlbfs/inode.c | 3 + trunk/fs/jbd/checkpoint.c | 418 ++-- trunk/fs/lockd/clntproc.c | 41 +- trunk/fs/lockd/host.c | 4 +- trunk/fs/lockd/mon.c | 1 + trunk/fs/lockd/svc.c | 4 +- trunk/fs/lockd/svc4proc.c | 15 +- trunk/fs/lockd/svclock.c | 42 +- trunk/fs/lockd/svcproc.c | 14 +- trunk/fs/lockd/xdr4.c | 4 +- trunk/fs/locks.c | 20 +- trunk/fs/nfs/Makefile | 1 - trunk/fs/nfs/callback.c | 3 +- trunk/fs/nfs/callback.h | 1 - trunk/fs/nfs/callback_proc.c | 4 +- trunk/fs/nfs/delegation.c | 47 +- trunk/fs/nfs/delegation.h | 2 - trunk/fs/nfs/dir.c | 4 +- trunk/fs/nfs/direct.c | 57 +- trunk/fs/nfs/idmap.c | 9 - trunk/fs/nfs/inode.c | 178 +- trunk/fs/nfs/mount_clnt.c | 1 + trunk/fs/nfs/nfs2xdr.c | 21 +- trunk/fs/nfs/nfs3proc.c | 70 +- trunk/fs/nfs/nfs3xdr.c | 2 +- trunk/fs/nfs/nfs4_fs.h | 20 +- trunk/fs/nfs/nfs4proc.c | 1480 +++++-------- trunk/fs/nfs/nfs4renewd.c | 14 +- trunk/fs/nfs/nfs4state.c | 183 +- trunk/fs/nfs/nfs4xdr.c | 187 +- trunk/fs/nfs/nfsroot.c | 4 +- trunk/fs/nfs/proc.c | 31 +- trunk/fs/nfs/read.c | 16 +- trunk/fs/nfs/sysctl.c | 84 - trunk/fs/nfs/unlink.c | 30 +- trunk/fs/nfs/write.c | 89 +- trunk/fs/nfsd/nfs3proc.c | 11 +- trunk/fs/nfsd/nfs3xdr.c | 47 +- trunk/fs/nfsd/nfs4callback.c | 11 +- trunk/fs/nfsd/nfsxdr.c | 48 +- trunk/fs/nfsd/vfs.c | 40 +- trunk/fs/partitions/Kconfig | 2 +- trunk/fs/partitions/ibm.c | 30 +- trunk/fs/proc/array.c | 2 +- trunk/fs/ramfs/Makefile | 4 +- trunk/fs/ramfs/file-mmu.c | 57 - trunk/fs/ramfs/file-nommu.c | 292 --- trunk/fs/ramfs/inode.c | 22 +- trunk/fs/ramfs/internal.h | 15 - trunk/fs/ufs/dir.c | 2 +- trunk/include/asm-alpha/atomic.h | 1 - trunk/include/asm-alpha/dma-mapping.h | 2 +- trunk/include/asm-alpha/hardirq.h | 2 - trunk/include/asm-alpha/mman.h | 1 - trunk/include/asm-arm/atomic.h | 1 - trunk/include/asm-arm/mman.h | 1 - trunk/include/asm-arm26/atomic.h | 1 - trunk/include/asm-arm26/mman.h | 1 - trunk/include/asm-cris/atomic.h | 1 - trunk/include/asm-cris/mman.h | 1 - trunk/include/asm-frv/atomic.h | 1 - trunk/include/asm-frv/futex.h | 42 +- trunk/include/asm-frv/mman.h | 1 - trunk/include/asm-frv/signal.h | 1 + trunk/include/asm-generic/atomic.h | 116 - trunk/include/asm-generic/vmlinux.lds.h | 4 - trunk/include/asm-h8300/atomic.h | 1 - trunk/include/asm-h8300/irq.h | 5 + trunk/include/asm-h8300/mman.h | 1 - trunk/include/asm-i386/atomic.h | 1 - trunk/include/asm-i386/bitops.h | 26 +- trunk/include/asm-i386/bugs.h | 23 +- trunk/include/asm-i386/cacheflush.h | 4 - trunk/include/asm-i386/desc.h | 8 +- .../include/asm-i386/mach-bigsmp/mach_apic.h | 79 +- .../asm-i386/mach-bigsmp/mach_apicdef.h | 4 +- trunk/include/asm-i386/mman.h | 1 - trunk/include/asm-i386/mmzone.h | 5 + trunk/include/asm-i386/module.h | 4 +- trunk/include/asm-i386/mpspec_def.h | 2 +- trunk/include/asm-i386/segment.h | 14 - trunk/include/asm-i386/system.h | 31 +- trunk/include/asm-i386/unistd.h | 2 +- trunk/include/asm-ia64/atomic.h | 1 - trunk/include/asm-ia64/mman.h | 1 - trunk/include/asm-ia64/unistd.h | 2 +- trunk/include/asm-m32r/assembler.h | 10 +- trunk/include/asm-m32r/atomic.h | 1 - trunk/include/asm-m32r/cacheflush.h | 2 +- trunk/include/asm-m32r/irq.h | 16 - trunk/include/asm-m32r/m32102.h | 38 +- .../include/asm-m32r/m32104ut/m32104ut_pld.h | 163 -- trunk/include/asm-m32r/m32r.h | 8 +- trunk/include/asm-m32r/mman.h | 1 - trunk/include/asm-m32r/system.h | 12 +- trunk/include/asm-m32r/unistd.h | 12 +- trunk/include/asm-m68k/atomic.h | 1 - trunk/include/asm-m68k/irq.h | 2 + trunk/include/asm-m68k/mman.h | 1 - trunk/include/asm-m68knommu/atomic.h | 1 - trunk/include/asm-m68knommu/irq.h | 6 +- trunk/include/asm-mips/atomic.h | 1 - trunk/include/asm-mips/mman.h | 1 - trunk/include/asm-mips/riscos-syscall.h | 979 +++++++++ trunk/include/asm-parisc/atomic.h | 1 - trunk/include/asm-parisc/mman.h | 1 - trunk/include/asm-powerpc/atomic.h | 1 - trunk/include/asm-powerpc/mman.h | 1 - trunk/include/asm-ppc/ibm_ocp.h | 1 + trunk/include/asm-ppc/io.h | 2 - trunk/include/asm-ppc/mpc52xx.h | 13 +- trunk/include/asm-s390/atomic.h | 174 +- trunk/include/asm-s390/ccwdev.h | 3 + trunk/include/asm-s390/mman.h | 1 - trunk/include/asm-s390/qdio.h | 8 +- trunk/include/asm-s390/s390_rdev.h | 15 - trunk/include/asm-s390/uaccess.h | 14 +- trunk/include/asm-s390/unistd.h | 2 +- trunk/include/asm-s390/vtoc.h | 24 - trunk/include/asm-sh/atomic.h | 1 - trunk/include/asm-sh/mman.h | 1 - trunk/include/asm-sh64/atomic.h | 1 - trunk/include/asm-sparc/atomic.h | 1 - trunk/include/asm-sparc/mman.h | 1 - trunk/include/asm-sparc64/atomic.h | 1 - trunk/include/asm-sparc64/mman.h | 1 - trunk/include/asm-v850/atomic.h | 1 - trunk/include/asm-v850/mman.h | 1 - trunk/include/asm-x86_64/atomic.h | 1 - trunk/include/asm-x86_64/cacheflush.h | 4 - trunk/include/asm-x86_64/mman.h | 1 - trunk/include/asm-x86_64/mpspec.h | 2 +- trunk/include/asm-x86_64/pgtable.h | 2 - trunk/include/asm-x86_64/system.h | 2 - trunk/include/asm-xtensa/atomic.h | 1 - trunk/include/asm-xtensa/mman.h | 1 - trunk/include/keys/user-type.h | 1 + trunk/include/linux/ata.h | 8 +- trunk/include/linux/blkdev.h | 91 +- trunk/include/linux/bootmem.h | 46 +- trunk/include/linux/dm-ioctl.h | 11 +- trunk/include/linux/elevator.h | 1 - trunk/include/linux/fs.h | 3 +- trunk/include/linux/fuse.h | 24 +- trunk/include/linux/hugetlb.h | 4 +- trunk/include/linux/i2o.h | 1940 ++++++++--------- trunk/include/linux/irq.h | 13 +- trunk/include/linux/jbd.h | 8 +- trunk/include/linux/key.h | 8 + trunk/include/linux/libata.h | 11 +- trunk/include/linux/lockd/lockd.h | 2 +- trunk/include/linux/mempolicy.h | 38 +- trunk/include/linux/mm.h | 55 +- trunk/include/linux/mmzone.h | 44 +- trunk/include/linux/nbd.h | 8 - trunk/include/linux/nfs_fs.h | 65 +- trunk/include/linux/nfs_idmap.h | 2 - trunk/include/linux/nfs_page.h | 12 +- trunk/include/linux/nfs_xdr.h | 89 +- trunk/include/linux/nfsd/xdr.h | 3 - trunk/include/linux/nfsd/xdr3.h | 1 - trunk/include/linux/page-flags.h | 91 +- trunk/include/linux/parport.h | 1 + trunk/include/linux/parport_pc.h | 4 +- trunk/include/linux/pci_ids.h | 10 - trunk/include/linux/raid/md.h | 4 +- trunk/include/linux/raid/md_k.h | 80 +- trunk/include/linux/raid/raid1.h | 14 +- trunk/include/linux/raid/raid10.h | 22 +- trunk/include/linux/raid/raid5.h | 7 +- trunk/include/linux/ramfs.h | 10 - trunk/include/linux/rmap.h | 1 - trunk/include/linux/sched.h | 25 +- trunk/include/linux/sunrpc/clnt.h | 5 +- trunk/include/linux/sunrpc/gss_spkm3.h | 2 +- trunk/include/linux/sunrpc/sched.h | 48 +- trunk/include/linux/sunrpc/xdr.h | 6 + trunk/include/linux/sunrpc/xprt.h | 12 +- trunk/include/linux/suspend.h | 8 +- trunk/include/linux/swap.h | 2 +- trunk/include/linux/writeback.h | 9 +- trunk/include/scsi/scsi_driver.h | 1 + trunk/include/scsi/scsi_host.h | 7 +- trunk/init/Kconfig | 3 +- trunk/init/do_mounts_md.c | 22 +- trunk/init/do_mounts_rd.c | 4 +- trunk/init/main.c | 5 - trunk/ipc/shm.c | 18 +- trunk/kernel/acct.c | 16 +- trunk/kernel/futex.c | 7 - trunk/kernel/irq/manage.c | 2 - trunk/kernel/irq/proc.c | 4 +- trunk/kernel/module.c | 3 +- trunk/kernel/panic.c | 4 +- trunk/kernel/power/disk.c | 92 +- trunk/kernel/power/power.h | 24 +- trunk/kernel/power/snapshot.c | 89 +- trunk/kernel/power/swsusp.c | 1020 +++++---- trunk/kernel/sysctl.c | 6 +- trunk/lib/Kconfig.debug | 5 +- trunk/lib/swiotlb.c | 3 +- trunk/mm/Kconfig | 2 +- trunk/mm/bootmem.c | 58 +- trunk/mm/filemap.c | 5 +- trunk/mm/hugetlb.c | 192 +- trunk/mm/internal.h | 21 +- trunk/mm/madvise.c | 35 - trunk/mm/memory.c | 32 +- trunk/mm/memory_hotplug.c | 1 + trunk/mm/mempolicy.c | 102 +- trunk/mm/nommu.c | 7 - trunk/mm/page-writeback.c | 10 +- trunk/mm/page_alloc.c | 343 ++- trunk/mm/rmap.c | 57 +- trunk/mm/shmem.c | 34 +- trunk/mm/swap.c | 27 +- trunk/mm/swap_state.c | 4 +- trunk/mm/swapfile.c | 20 - trunk/mm/tiny-shmem.c | 29 +- trunk/mm/truncate.c | 44 +- trunk/mm/vmscan.c | 123 +- trunk/net/sunrpc/auth_gss/gss_krb5_mech.c | 10 +- trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c | 10 +- trunk/net/sunrpc/auth_gss/gss_spkm3_seal.c | 11 +- trunk/net/sunrpc/auth_gss/gss_spkm3_token.c | 3 +- trunk/net/sunrpc/auth_gss/gss_spkm3_unseal.c | 2 +- trunk/net/sunrpc/clnt.c | 107 +- trunk/net/sunrpc/pmap_clnt.c | 17 +- trunk/net/sunrpc/rpc_pipe.c | 9 +- trunk/net/sunrpc/sched.c | 222 +- trunk/net/sunrpc/sunrpc_syms.c | 4 + trunk/net/sunrpc/svcauth_unix.c | 14 +- trunk/net/sunrpc/svcsock.c | 2 +- trunk/net/sunrpc/xdr.c | 21 + trunk/net/sunrpc/xprt.c | 66 +- trunk/net/sunrpc/xprtsock.c | 31 +- trunk/security/keys/internal.h | 1 + trunk/security/keys/key.c | 58 +- trunk/security/keys/keyring.c | 66 +- trunk/security/keys/user_defined.c | 33 + trunk/security/selinux/selinuxfs.c | 4 +- trunk/security/selinux/ss/avtab.c | 2 +- trunk/security/selinux/ss/policydb.c | 2 +- trunk/sound/oss/ad1848.c | 92 + trunk/sound/oss/cs4281/cs4281m.c | 21 +- trunk/sound/oss/cs4281/cs4281pm-24.c | 39 + trunk/sound/oss/cs46xx.c | 60 + trunk/sound/oss/cs46xxpm-24.h | 4 + trunk/sound/oss/maestro.c | 149 ++ trunk/sound/oss/nm256_audio.c | 47 + trunk/sound/oss/opl3sa2.c | 110 + 556 files changed, 12140 insertions(+), 17249 deletions(-) delete mode 100644 trunk/arch/frv/kernel/futex.c delete mode 100644 trunk/arch/m32r/kernel/io_m32104ut.c delete mode 100644 trunk/arch/m32r/kernel/setup_m32104ut.c delete mode 100644 trunk/arch/m32r/m32104ut/defconfig.m32104ut create mode 100644 trunk/arch/ppc/platforms/mpc5200.c delete mode 100644 trunk/arch/s390/crypto/aes_s390.c delete mode 100644 trunk/arch/s390/crypto/crypt_s390_query.c rename trunk/arch/s390/crypto/{crypt_s390.h => crypt_z990.h} (50%) create mode 100644 trunk/arch/s390/crypto/crypt_z990_query.c rename trunk/arch/s390/crypto/{des_s390.c => des_z990.c} (81%) rename trunk/arch/s390/crypto/{sha1_s390.c => sha1_z990.c} (82%) delete mode 100644 trunk/arch/s390/crypto/sha256_s390.c delete mode 100644 trunk/arch/s390/oprofile/backtrace.c delete mode 100644 trunk/arch/um/os-Linux/umid.c delete mode 100644 trunk/drivers/s390/cio/schid.h delete mode 100644 trunk/drivers/s390/s390_rdev.c delete mode 100644 trunk/fs/nfs/sysctl.c delete mode 100644 trunk/fs/ramfs/file-mmu.c delete mode 100644 trunk/fs/ramfs/file-nommu.c delete mode 100644 trunk/fs/ramfs/internal.h delete mode 100644 trunk/include/asm-generic/atomic.h delete mode 100644 trunk/include/asm-m32r/m32104ut/m32104ut_pld.h create mode 100644 trunk/include/asm-mips/riscos-syscall.h delete mode 100644 trunk/include/asm-s390/s390_rdev.h diff --git a/[refs] b/[refs] index acc4b7c6d873..ef54b16f4904 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 47853e7fa588bef826c9799a87b33904b32bd905 +refs/heads/master: 253dfa6e465c054a73bd3b13af51c34c9d8d233d diff --git a/trunk/Documentation/block/biodoc.txt b/trunk/Documentation/block/biodoc.txt index 8e63831971d5..303c57a7fad9 100644 --- a/trunk/Documentation/block/biodoc.txt +++ b/trunk/Documentation/block/biodoc.txt @@ -263,8 +263,14 @@ A flag in the bio structure, BIO_BARRIER is used to identify a barrier i/o. The generic i/o scheduler would make sure that it places the barrier request and all other requests coming after it after all the previous requests in the queue. Barriers may be implemented in different ways depending on the -driver. For more details regarding I/O barriers, please read barrier.txt -in this directory. +driver. A SCSI driver for example could make use of ordered tags to +preserve the necessary ordering with a lower impact on throughput. For IDE +this might be two sync cache flush: a pre and post flush when encountering +a barrier write. + +There is a provision for queues to indicate what kind of barriers they +can provide. This is as of yet unmerged, details will be added here once it +is in the kernel. 1.2.2 Request Priority/Latency diff --git a/trunk/Documentation/kbuild/modules.txt b/trunk/Documentation/kbuild/modules.txt index 1c0db652b366..7e77f93634ea 100644 --- a/trunk/Documentation/kbuild/modules.txt +++ b/trunk/Documentation/kbuild/modules.txt @@ -18,6 +18,7 @@ In this document you will find information about: === 5. Include files --- 5.1 How to include files from the kernel include dir --- 5.2 External modules using an include/ dir + --- 5.3 External modules using several directories === 6. Module installation --- 6.1 INSTALL_MOD_PATH --- 6.2 INSTALL_MOD_DIR @@ -344,6 +345,45 @@ directory and therefore needs to deal with this in their kbuild file. Note that in the assignment there is no space between -I and the path. This is a kbuild limitation: there must be no space present. +--- 5.3 External modules using several directories + + If an external module does not follow the usual kernel style but + decide to spread files over several directories then kbuild can + support this too. + + Consider the following example: + + | + +- src/complex_main.c + | +- hal/hardwareif.c + | +- hal/include/hardwareif.h + +- include/complex.h + + To build a single module named complex.ko we then need the following + kbuild file: + + Kbuild: + obj-m := complex.o + complex-y := src/complex_main.o + complex-y += src/hal/hardwareif.o + + EXTRA_CFLAGS := -I$(src)/include + EXTRA_CFLAGS += -I$(src)src/hal/include + + + kbuild knows how to handle .o files located in another directory - + although this is NOT reccommended practice. The syntax is to specify + the directory relative to the directory where the Kbuild file is + located. + + To find the .h files we have to explicitly tell kbuild where to look + for the .h files. When kbuild executes current directory is always + the root of the kernel tree (argument to -C) and therefore we have to + tell kbuild how to find the .h files using absolute paths. + $(src) will specify the absolute path to the directory where the + Kbuild file are located when being build as an external module. + Therefore -I$(src)/ is used to point out the directory of the Kbuild + file and any additional path are just appended. === 6. Module installation diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index a482fde09bbb..61a56b100c62 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -910,14 +910,6 @@ running once the system is up. nfsroot= [NFS] nfs root filesystem for disk-less boxes. See Documentation/nfsroot.txt. - nfs.callback_tcpport= - [NFS] set the TCP port on which the NFSv4 callback - channel should listen. - - nfs.idmap_cache_timeout= - [NFS] set the maximum lifetime for idmapper cache - entries. - nmi_watchdog= [KNL,BUGS=IA-32] Debugging features for SMP kernels no387 [BUGS=IA-32] Tells the kernel to use the 387 maths diff --git a/trunk/Documentation/keys.txt b/trunk/Documentation/keys.txt index 6304db59bfe4..31154882000a 100644 --- a/trunk/Documentation/keys.txt +++ b/trunk/Documentation/keys.txt @@ -860,6 +860,24 @@ The structure has a number of fields, some of which are mandatory: It is safe to sleep in this method. + (*) int (*duplicate)(struct key *key, const struct key *source); + + If this type of key can be duplicated, then this method should be + provided. It is called to copy the payload attached to the source into the + new key. The data length on the new key will have been updated and the + quota adjusted already. + + This method will be called with the source key's semaphore read-locked to + prevent its payload from being changed, thus RCU constraints need not be + applied to the source key. + + This method does not have to lock the destination key in order to attach a + payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags + prevents anything else from gaining access to the key. + + It is safe to sleep in this method. + + (*) int (*update)(struct key *key, const void *data, size_t datalen); If this type of key can be updated, then this method should be provided. diff --git a/trunk/Documentation/md.txt b/trunk/Documentation/md.txt index 03a13c462cf2..23e6cce40f9c 100644 --- a/trunk/Documentation/md.txt +++ b/trunk/Documentation/md.txt @@ -51,30 +51,6 @@ superblock can be autodetected and run at boot time. The kernel parameter "raid=partitionable" (or "raid=part") means that all auto-detected arrays are assembled as partitionable. -Boot time assembly of degraded/dirty arrays -------------------------------------------- - -If a raid5 or raid6 array is both dirty and degraded, it could have -undetectable data corruption. This is because the fact that it is -'dirty' means that the parity cannot be trusted, and the fact that it -is degraded means that some datablocks are missing and cannot reliably -be reconstructed (due to no parity). - -For this reason, md will normally refuse to start such an array. This -requires the sysadmin to take action to explicitly start the array -desipite possible corruption. This is normally done with - mdadm --assemble --force .... - -This option is not really available if the array has the root -filesystem on it. In order to support this booting from such an -array, md supports a module parameter "start_dirty_degraded" which, -when set to 1, bypassed the checks and will allows dirty degraded -arrays to be started. - -So, to boot with a root filesystem of a dirty degraded raid[56], use - - md-mod.start_dirty_degraded=1 - Superblock formats ------------------ @@ -165,70 +141,6 @@ All md devices contain: in a fully functional array. If this is not yet known, the file will be empty. If an array is being resized (not currently possible) this will contain the larger of the old and new sizes. - Some raid level (RAID1) allow this value to be set while the - array is active. This will reconfigure the array. Otherwise - it can only be set while assembling an array. - - chunk_size - This is the size if bytes for 'chunks' and is only relevant to - raid levels that involve striping (1,4,5,6,10). The address space - of the array is conceptually divided into chunks and consecutive - chunks are striped onto neighbouring devices. - The size should be atleast PAGE_SIZE (4k) and should be a power - of 2. This can only be set while assembling an array - - component_size - For arrays with data redundancy (i.e. not raid0, linear, faulty, - multipath), all components must be the same size - or at least - there must a size that they all provide space for. This is a key - part or the geometry of the array. It is measured in sectors - and can be read from here. Writing to this value may resize - the array if the personality supports it (raid1, raid5, raid6), - and if the component drives are large enough. - - metadata_version - This indicates the format that is being used to record metadata - about the array. It can be 0.90 (traditional format), 1.0, 1.1, - 1.2 (newer format in varying locations) or "none" indicating that - the kernel isn't managing metadata at all. - - level - The raid 'level' for this array. The name will often (but not - always) be the same as the name of the module that implements the - level. To be auto-loaded the module must have an alias - md-$LEVEL e.g. md-raid5 - This can be written only while the array is being assembled, not - after it is started. - - new_dev - This file can be written but not read. The value written should - be a block device number as major:minor. e.g. 8:0 - This will cause that device to be attached to the array, if it is - available. It will then appear at md/dev-XXX (depending on the - name of the device) and further configuration is then possible. - - sync_speed_min - sync_speed_max - This are similar to /proc/sys/dev/raid/speed_limit_{min,max} - however they only apply to the particular array. - If no value has been written to these, of if the word 'system' - is written, then the system-wide value is used. If a value, - in kibibytes-per-second is written, then it is used. - When the files are read, they show the currently active value - followed by "(local)" or "(system)" depending on whether it is - a locally set or system-wide value. - - sync_completed - This shows the number of sectors that have been completed of - whatever the current sync_action is, followed by the number of - sectors in total that could need to be processed. The two - numbers are separated by a '/' thus effectively showing one - value, a fraction of the process that is complete. - - sync_speed - This shows the current actual speed, in K/sec, of the current - sync_action. It is averaged over the last 30 seconds. - As component devices are added to an md array, they appear in the 'md' directory as new directories named @@ -255,38 +167,6 @@ Each directory contains: of being recoverred to This list make grow in future. - errors - An approximate count of read errors that have been detected on - this device but have not caused the device to be evicted from - the array (either because they were corrected or because they - happened while the array was read-only). When using version-1 - metadata, this value persists across restarts of the array. - - This value can be written while assembling an array thus - providing an ongoing count for arrays with metadata managed by - userspace. - - slot - This gives the role that the device has in the array. It will - either be 'none' if the device is not active in the array - (i.e. is a spare or has failed) or an integer less than the - 'raid_disks' number for the array indicating which possition - it currently fills. This can only be set while assembling an - array. A device for which this is set is assumed to be working. - - offset - This gives the location in the device (in sectors from the - start) where data from the array will be stored. Any part of - the device before this offset us not touched, unless it is - used for storing metadata (Formats 1.1 and 1.2). - - size - The amount of the device, after the offset, that can be used - for storage of data. This will normally be the same as the - component_size. This can be written while assembling an - array. If a value less than the current component_size is - written, component_size will be reduced to this value. - An active md device will also contain and entry for each active device in the array. These are named diff --git a/trunk/Documentation/power/interface.txt b/trunk/Documentation/power/interface.txt index bd4ffb5bd49a..f5ebda5f4276 100644 --- a/trunk/Documentation/power/interface.txt +++ b/trunk/Documentation/power/interface.txt @@ -41,14 +41,3 @@ to. Writing to this file will accept one of It will only change to 'firmware' or 'platform' if the system supports it. -/sys/power/image_size controls the size of the image created by -the suspend-to-disk mechanism. It can be written a string -representing a non-negative integer that will be used as an upper -limit of the image size, in megabytes. The suspend-to-disk mechanism will -do its best to ensure the image size will not exceed that number. However, -if this turns out to be impossible, it will try to suspend anyway using the -smallest image possible. In particular, if "0" is written to this file, the -suspend image will be as small as possible. - -Reading from this file will display the current image size limit, which -is set to 500 MB by default. diff --git a/trunk/Documentation/power/swsusp.txt b/trunk/Documentation/power/swsusp.txt index cd0fcd89a6f0..b0d50840788e 100644 --- a/trunk/Documentation/power/swsusp.txt +++ b/trunk/Documentation/power/swsusp.txt @@ -27,11 +27,6 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state echo platform > /sys/power/disk; echo disk > /sys/power/state -If you want to limit the suspend image size to N megabytes, do - -echo N > /sys/power/image_size - -before suspend (it is limited to 500 MB by default). Encrypted suspend image: ------------------------ diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 08e2dcf36f74..e9db0d6b928a 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -258,13 +258,6 @@ P: Ivan Kokshaysky M: ink@jurassic.park.msu.ru S: Maintained for 2.4; PCI support for 2.6. -AMD GEODE PROCESSOR/CHIPSET SUPPORT -P: Jordan Crouse -M: info-linux@geode.amd.com -L: info-linux@geode.amd.com -W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html -S: Supported - APM DRIVER P: Stephen Rothwell M: sfr@canb.auug.org.au @@ -696,6 +689,13 @@ M: pc300@cyclades.com W: http://www.cyclades.com/ S: Supported +DAC960 RAID CONTROLLER DRIVER +P: Dave Olien +M dmo@osdl.org +W: http://www.osdl.org/archive/dmo/DAC960 +L: linux-kernel@vger.kernel.org +S: Maintained + DAMA SLAVE for AX.25 P: Joerg Reuter M: jreuter@yaina.de diff --git a/trunk/arch/alpha/Kconfig b/trunk/arch/alpha/Kconfig index 153337ff1d7b..786491f9ceb2 100644 --- a/trunk/arch/alpha/Kconfig +++ b/trunk/arch/alpha/Kconfig @@ -40,19 +40,6 @@ config GENERIC_IOMAP bool default n -config GENERIC_HARDIRQS - bool - default y - -config GENERIC_IRQ_PROBE - bool - default y - -config AUTO_IRQ_AFFINITY - bool - depends on SMP - default y - source "init/Kconfig" diff --git a/trunk/arch/alpha/kernel/alpha_ksyms.c b/trunk/arch/alpha/kernel/alpha_ksyms.c index f3e98f837784..24ae9a366073 100644 --- a/trunk/arch/alpha/kernel/alpha_ksyms.c +++ b/trunk/arch/alpha/kernel/alpha_ksyms.c @@ -175,6 +175,7 @@ EXPORT_SYMBOL(up); */ #ifdef CONFIG_SMP +EXPORT_SYMBOL(synchronize_irq); EXPORT_SYMBOL(flush_tlb_mm); EXPORT_SYMBOL(flush_tlb_range); EXPORT_SYMBOL(flush_tlb_page); diff --git a/trunk/arch/alpha/kernel/irq.c b/trunk/arch/alpha/kernel/irq.c index 76be5cf0de13..b6114f5c0d2b 100644 --- a/trunk/arch/alpha/kernel/irq.c +++ b/trunk/arch/alpha/kernel/irq.c @@ -32,25 +32,214 @@ #include #include +/* + * Controller mappings for all interrupt sources: + */ +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { + [0 ... NR_IRQS-1] = { + .handler = &no_irq_type, + .lock = SPIN_LOCK_UNLOCKED + } +}; + +static void register_irq_proc(unsigned int irq); + volatile unsigned long irq_err_count; -void ack_bad_irq(unsigned int irq) +/* + * Special irq handlers. + */ + +irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) +{ + return IRQ_NONE; +} + +/* + * Generic no controller code + */ + +static void no_irq_enable_disable(unsigned int irq) { } +static unsigned int no_irq_startup(unsigned int irq) { return 0; } + +static void +no_irq_ack(unsigned int irq) { irq_err_count++; printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq); } +struct hw_interrupt_type no_irq_type = { + .typename = "none", + .startup = no_irq_startup, + .shutdown = no_irq_enable_disable, + .enable = no_irq_enable_disable, + .disable = no_irq_enable_disable, + .ack = no_irq_ack, + .end = no_irq_enable_disable, +}; + +int +handle_IRQ_event(unsigned int irq, struct pt_regs *regs, + struct irqaction *action) +{ + int status = 1; /* Force the "do bottom halves" bit */ + int ret; + + do { + if (!(action->flags & SA_INTERRUPT)) + local_irq_enable(); + else + local_irq_disable(); + + ret = action->handler(irq, action->dev_id, regs); + if (ret == IRQ_HANDLED) + status |= action->flags; + action = action->next; + } while (action); + if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + local_irq_disable(); + + return status; +} + +/* + * Generic enable/disable code: this just calls + * down into the PIC-specific version for the actual + * hardware disable after having gotten the irq + * controller lock. + */ +void inline +disable_irq_nosync(unsigned int irq) +{ + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + if (!desc->depth++) { + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); + } + spin_unlock_irqrestore(&desc->lock, flags); +} + +/* + * Synchronous version of the above, making sure the IRQ is + * no longer running on any other IRQ.. + */ +void +disable_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + synchronize_irq(irq); +} + +void +enable_irq(unsigned int irq) +{ + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + switch (desc->depth) { + case 1: { + unsigned int status = desc->status & ~IRQ_DISABLED; + desc->status = status; + if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { + desc->status = status | IRQ_REPLAY; + hw_resend_irq(desc->handler,irq); + } + desc->handler->enable(irq); + /* fall-through */ + } + default: + desc->depth--; + break; + case 0: + printk(KERN_ERR "enable_irq() unbalanced from %p\n", + __builtin_return_address(0)); + } + spin_unlock_irqrestore(&desc->lock, flags); +} + +int +setup_irq(unsigned int irq, struct irqaction * new) +{ + int shared = 0; + struct irqaction *old, **p; + unsigned long flags; + irq_desc_t *desc = irq_desc + irq; + + if (desc->handler == &no_irq_type) + return -ENOSYS; + + /* + * Some drivers like serial.c use request_irq() heavily, + * so we have to be careful not to interfere with a + * running system. + */ + if (new->flags & SA_SAMPLE_RANDOM) { + /* + * This function might sleep, we want to call it first, + * outside of the atomic block. + * Yes, this might clear the entropy pool if the wrong + * driver is attempted to be loaded, without actually + * installing a new handler, but is this really a problem, + * only the sysadmin is able to do this. + */ + rand_initialize_irq(irq); + } + + /* + * The following block of code has to be executed atomically + */ + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&desc->lock,flags); + return -EBUSY; + } + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + *p = new; + + if (!shared) { + desc->depth = 0; + desc->status &= + ~(IRQ_DISABLED|IRQ_AUTODETECT|IRQ_WAITING|IRQ_INPROGRESS); + desc->handler->startup(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + return 0; +} + +static struct proc_dir_entry * root_irq_dir; +static struct proc_dir_entry * irq_dir[NR_IRQS]; + #ifdef CONFIG_SMP +static struct proc_dir_entry * smp_affinity_entry[NR_IRQS]; static char irq_user_affinity[NR_IRQS]; +static cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL }; -int -select_smp_affinity(unsigned int irq) +static void +select_smp_affinity(int irq) { static int last_cpu; int cpu = last_cpu + 1; - if (!irq_desc[irq].handler->set_affinity || irq_user_affinity[irq]) - return 1; + if (! irq_desc[irq].handler->set_affinity || irq_user_affinity[irq]) + return; while (!cpu_possible(cpu)) cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0); @@ -58,10 +247,208 @@ select_smp_affinity(unsigned int irq) irq_affinity[irq] = cpumask_of_cpu(cpu); irq_desc[irq].handler->set_affinity(irq, cpumask_of_cpu(cpu)); - return 0; } + +static int +irq_affinity_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); + if (count - len < 2) + return -EINVAL; + len += sprintf(page + len, "\n"); + return len; +} + +static int +irq_affinity_write_proc(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + int irq = (long) data, full_count = count, err; + cpumask_t new_value; + + if (!irq_desc[irq].handler->set_affinity) + return -EIO; + + err = cpumask_parse(buffer, count, new_value); + + /* The special value 0 means release control of the + affinity to kernel. */ + cpus_and(new_value, new_value, cpu_online_map); + if (cpus_empty(new_value)) { + irq_user_affinity[irq] = 0; + select_smp_affinity(irq); + } + /* Do not allow disabling IRQs completely - it's a too easy + way to make the system unusable accidentally :-) At least + one online CPU still has to be targeted. */ + else { + irq_affinity[irq] = new_value; + irq_user_affinity[irq] = 1; + irq_desc[irq].handler->set_affinity(irq, new_value); + } + + return full_count; +} + #endif /* CONFIG_SMP */ +#define MAX_NAMELEN 10 + +static void +register_irq_proc (unsigned int irq) +{ + char name [MAX_NAMELEN]; + + if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || + irq_dir[irq]) + return; + + memset(name, 0, MAX_NAMELEN); + sprintf(name, "%d", irq); + + /* create /proc/irq/1234 */ + irq_dir[irq] = proc_mkdir(name, root_irq_dir); + +#ifdef CONFIG_SMP + if (irq_desc[irq].handler->set_affinity) { + struct proc_dir_entry *entry; + /* create /proc/irq/1234/smp_affinity */ + entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); + + if (entry) { + entry->nlink = 1; + entry->data = (void *)(long)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + } + + smp_affinity_entry[irq] = entry; + } +#endif +} + +void +init_irq_proc (void) +{ + int i; + + /* create /proc/irq */ + root_irq_dir = proc_mkdir("irq", NULL); + +#ifdef CONFIG_SMP + /* create /proc/irq/prof_cpu_mask */ + create_prof_cpu_mask(root_irq_dir); +#endif + + /* + * Create entries for all existing IRQs. + */ + for (i = 0; i < ACTUAL_NR_IRQS; i++) { + if (irq_desc[i].handler == &no_irq_type) + continue; + register_irq_proc(i); + } +} + +int +request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, const char * devname, void *dev_id) +{ + int retval; + struct irqaction * action; + + if (irq >= ACTUAL_NR_IRQS) + return -EINVAL; + if (!handler) + return -EINVAL; + +#if 1 + /* + * Sanity-check: shared interrupts should REALLY pass in + * a real dev-ID, otherwise we'll have trouble later trying + * to figure out which interrupt is which (messes up the + * interrupt freeing logic etc). + */ + if ((irqflags & SA_SHIRQ) && !dev_id) { + printk(KERN_ERR + "Bad boy: %s (at %p) called us without a dev_id!\n", + devname, __builtin_return_address(0)); + } +#endif + + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + cpus_clear(action->mask); + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + +#ifdef CONFIG_SMP + select_smp_affinity(irq); +#endif + + retval = setup_irq(irq, action); + if (retval) + kfree(action); + return retval; +} + +EXPORT_SYMBOL(request_irq); + +void +free_irq(unsigned int irq, void *dev_id) +{ + irq_desc_t *desc; + struct irqaction **p; + unsigned long flags; + + if (irq >= ACTUAL_NR_IRQS) { + printk(KERN_CRIT "Trying to free IRQ%d\n", irq); + return; + } + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + for (;;) { + struct irqaction * action = *p; + if (action) { + struct irqaction **pp = p; + p = &action->next; + if (action->dev_id != dev_id) + continue; + + /* Found - now remove it from the list of entries. */ + *pp = action->next; + if (!desc->action) { + desc->status |= IRQ_DISABLED; + desc->handler->shutdown(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + +#ifdef CONFIG_SMP + /* Wait to make sure it's not being used on + another CPU. */ + while (desc->status & IRQ_INPROGRESS) + barrier(); +#endif + kfree(action); + return; + } + printk(KERN_ERR "Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); + return; + } +} + +EXPORT_SYMBOL(free_irq); + int show_interrupts(struct seq_file *p, void *v) { @@ -144,6 +531,10 @@ handle_irq(int irq, struct pt_regs * regs) * 0 return value means that this irq is already being * handled by some other CPU. (or is disabled) */ + int cpu = smp_processor_id(); + irq_desc_t *desc = irq_desc + irq; + struct irqaction * action; + unsigned int status; static unsigned int illegal_count=0; if ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS ) { @@ -155,8 +546,229 @@ handle_irq(int irq, struct pt_regs * regs) } irq_enter(); - local_irq_disable(); - __do_IRQ(irq, regs); - local_irq_enable(); + kstat_cpu(cpu).irqs[irq]++; + spin_lock_irq(&desc->lock); /* mask also the higher prio events */ + desc->handler->ack(irq); + /* + * REPLAY is when Linux resends an IRQ that was dropped earlier. + * WAITING is used by probe to mark irqs that are being tested. + */ + status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); + status |= IRQ_PENDING; /* we _want_ to handle it */ + + /* + * If the IRQ is disabled for whatever reason, we cannot + * use the action we have. + */ + action = NULL; + if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + action = desc->action; + status &= ~IRQ_PENDING; /* we commit to handling */ + status |= IRQ_INPROGRESS; /* we are handling it */ + } + desc->status = status; + + /* + * If there is no IRQ handler or it was disabled, exit early. + * Since we set PENDING, if another processor is handling + * a different instance of this same irq, the other processor + * will take care of it. + */ + if (!action) + goto out; + + /* + * Edge triggered interrupts need to remember pending events. + * This applies to any hw interrupts that allow a second + * instance of the same irq to arrive while we are in handle_irq + * or in the handler. But the code here only handles the _second_ + * instance of the irq, not the third or fourth. So it is mostly + * useful for irq hardware that does not mask cleanly in an + * SMP environment. + */ + for (;;) { + spin_unlock(&desc->lock); + handle_IRQ_event(irq, regs, action); + spin_lock(&desc->lock); + + if (!(desc->status & IRQ_PENDING) + || (desc->status & IRQ_LEVEL)) + break; + desc->status &= ~IRQ_PENDING; + } + desc->status &= ~IRQ_INPROGRESS; +out: + /* + * The ->end() handler has to deal with interrupts which got + * disabled while the handler was running. + */ + desc->handler->end(irq); + spin_unlock(&desc->lock); + irq_exit(); } + +/* + * IRQ autodetection code.. + * + * This depends on the fact that any interrupt that + * comes in on to an unassigned handler will get stuck + * with "IRQ_WAITING" cleared and the interrupt + * disabled. + */ +unsigned long +probe_irq_on(void) +{ + int i; + irq_desc_t *desc; + unsigned long delay; + unsigned long val; + + /* Something may have generated an irq long ago and we want to + flush such a longstanding irq before considering it as spurious. */ + for (i = NR_IRQS-1; i >= 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!irq_desc[i].action) + irq_desc[i].handler->startup(i); + spin_unlock_irq(&desc->lock); + } + + /* Wait for longstanding interrupts to trigger. */ + for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) + /* about 20ms delay */ barrier(); + + /* enable any unassigned irqs (we must startup again here because + if a longstanding irq happened in the previous stage, it may have + masked itself) first, enable any unassigned irqs. */ + for (i = NR_IRQS-1; i >= 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!desc->action) { + desc->status |= IRQ_AUTODETECT | IRQ_WAITING; + if (desc->handler->startup(i)) + desc->status |= IRQ_PENDING; + } + spin_unlock_irq(&desc->lock); + } + + /* + * Wait for spurious interrupts to trigger + */ + for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) + /* about 100ms delay */ barrier(); + + /* + * Now filter out any obviously spurious interrupts + */ + val = 0; + for (i=0; ilock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + /* It triggered already - consider it spurious. */ + if (!(status & IRQ_WAITING)) { + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } else + if (i < 32) + val |= 1 << i; + } + spin_unlock_irq(&desc->lock); + } + + return val; +} + +EXPORT_SYMBOL(probe_irq_on); + +/* + * Return a mask of triggered interrupts (this + * can handle only legacy ISA interrupts). + */ +unsigned int +probe_irq_mask(unsigned long val) +{ + int i; + unsigned int mask; + + mask = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + /* We only react to ISA interrupts */ + if (!(status & IRQ_WAITING)) { + if (i < 16) + mask |= 1 << i; + } + + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } + spin_unlock_irq(&desc->lock); + } + + return mask & val; +} + +/* + * Get the result of the IRQ probe.. A negative result means that + * we have several candidates (but we return the lowest-numbered + * one). + */ + +int +probe_irq_off(unsigned long val) +{ + int i, irq_found, nr_irqs; + + nr_irqs = 0; + irq_found = 0; + for (i=0; ilock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + if (!(status & IRQ_WAITING)) { + if (!nr_irqs) + irq_found = i; + nr_irqs++; + } + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } + spin_unlock_irq(&desc->lock); + } + + if (nr_irqs > 1) + irq_found = -irq_found; + return irq_found; +} + +EXPORT_SYMBOL(probe_irq_off); + +#ifdef CONFIG_SMP +void synchronize_irq(unsigned int irq) +{ + /* is there anything to synchronize with? */ + if (!irq_desc[irq].action) + return; + + while (irq_desc[irq].status & IRQ_INPROGRESS) + barrier(); +} +#endif diff --git a/trunk/arch/cris/arch-v10/kernel/kgdb.c b/trunk/arch/cris/arch-v10/kernel/kgdb.c index 34528da98817..b72e6a91a639 100644 --- a/trunk/arch/cris/arch-v10/kernel/kgdb.c +++ b/trunk/arch/cris/arch-v10/kernel/kgdb.c @@ -569,6 +569,12 @@ gdb_cris_strtol (const char *s, char **endptr, int base) return x; } +int +double_this(int x) +{ + return 2 * x; +} + /********************************* Register image ****************************/ /* Copy the content of a register image into another. The size n is the size of the register image. Due to struct assignment generation of diff --git a/trunk/arch/frv/kernel/Makefile b/trunk/arch/frv/kernel/Makefile index 422f30ede575..981c2c7dec0d 100644 --- a/trunk/arch/frv/kernel/Makefile +++ b/trunk/arch/frv/kernel/Makefile @@ -20,4 +20,3 @@ obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o obj-$(CONFIG_PM) += pm.o cmode.o obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o obj-$(CONFIG_SYSCTL) += sysctl.o -obj-$(CONFIG_FUTEX) += futex.o diff --git a/trunk/arch/frv/kernel/entry.S b/trunk/arch/frv/kernel/entry.S index 5f6548388b74..ad10ea595459 100644 --- a/trunk/arch/frv/kernel/entry.S +++ b/trunk/arch/frv/kernel/entry.S @@ -1076,7 +1076,7 @@ __entry_work_notifysig: LEDS 0x6410 ori.p gr4,#0,gr8 call do_notify_resume - bra __entry_resume_userspace + bra __entry_return_direct # perform syscall entry tracing __syscall_trace_entry: diff --git a/trunk/arch/frv/kernel/futex.c b/trunk/arch/frv/kernel/futex.c deleted file mode 100644 index eae874a970c6..000000000000 --- a/trunk/arch/frv/kernel/futex.c +++ /dev/null @@ -1,242 +0,0 @@ -/* futex.c: futex operations - * - * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * 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. - */ - -#include -#include -#include -#include - -/* - * the various futex operations; MMU fault checking is ignored under no-MMU - * conditions - */ -static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval) -{ - int oldval, ret; - - asm("0: \n" - " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ - " ckeq icc3,cc7 \n" - "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ - " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ - "2: cst.p %3,%M0 ,cc3,#1 \n" - " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ - " beq icc3,#0,0b \n" - " setlos 0,%2 \n" - "3: \n" - ".subsection 2 \n" - "4: setlos %5,%2 \n" - " bra 3b \n" - ".previous \n" - ".section __ex_table,\"a\" \n" - " .balign 8 \n" - " .long 1b,4b \n" - " .long 2b,4b \n" - ".previous" - : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) - : "3"(oparg), "i"(-EFAULT) - : "memory", "cc7", "cc3", "icc3" - ); - - *_oldval = oldval; - return ret; -} - -static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval) -{ - int oldval, ret; - - asm("0: \n" - " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ - " ckeq icc3,cc7 \n" - "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ - " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ - " add %1,%3,%3 \n" - "2: cst.p %3,%M0 ,cc3,#1 \n" - " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ - " beq icc3,#0,0b \n" - " setlos 0,%2 \n" - "3: \n" - ".subsection 2 \n" - "4: setlos %5,%2 \n" - " bra 3b \n" - ".previous \n" - ".section __ex_table,\"a\" \n" - " .balign 8 \n" - " .long 1b,4b \n" - " .long 2b,4b \n" - ".previous" - : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) - : "3"(oparg), "i"(-EFAULT) - : "memory", "cc7", "cc3", "icc3" - ); - - *_oldval = oldval; - return ret; -} - -static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval) -{ - int oldval, ret; - - asm("0: \n" - " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ - " ckeq icc3,cc7 \n" - "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ - " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ - " or %1,%3,%3 \n" - "2: cst.p %3,%M0 ,cc3,#1 \n" - " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ - " beq icc3,#0,0b \n" - " setlos 0,%2 \n" - "3: \n" - ".subsection 2 \n" - "4: setlos %5,%2 \n" - " bra 3b \n" - ".previous \n" - ".section __ex_table,\"a\" \n" - " .balign 8 \n" - " .long 1b,4b \n" - " .long 2b,4b \n" - ".previous" - : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) - : "3"(oparg), "i"(-EFAULT) - : "memory", "cc7", "cc3", "icc3" - ); - - *_oldval = oldval; - return ret; -} - -static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval) -{ - int oldval, ret; - - asm("0: \n" - " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ - " ckeq icc3,cc7 \n" - "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ - " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ - " and %1,%3,%3 \n" - "2: cst.p %3,%M0 ,cc3,#1 \n" - " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ - " beq icc3,#0,0b \n" - " setlos 0,%2 \n" - "3: \n" - ".subsection 2 \n" - "4: setlos %5,%2 \n" - " bra 3b \n" - ".previous \n" - ".section __ex_table,\"a\" \n" - " .balign 8 \n" - " .long 1b,4b \n" - " .long 2b,4b \n" - ".previous" - : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) - : "3"(oparg), "i"(-EFAULT) - : "memory", "cc7", "cc3", "icc3" - ); - - *_oldval = oldval; - return ret; -} - -static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval) -{ - int oldval, ret; - - asm("0: \n" - " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ - " ckeq icc3,cc7 \n" - "1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ - " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ - " xor %1,%3,%3 \n" - "2: cst.p %3,%M0 ,cc3,#1 \n" - " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ - " beq icc3,#0,0b \n" - " setlos 0,%2 \n" - "3: \n" - ".subsection 2 \n" - "4: setlos %5,%2 \n" - " bra 3b \n" - ".previous \n" - ".section __ex_table,\"a\" \n" - " .balign 8 \n" - " .long 1b,4b \n" - " .long 2b,4b \n" - ".previous" - : "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg) - : "3"(oparg), "i"(-EFAULT) - : "memory", "cc7", "cc3", "icc3" - ); - - *_oldval = oldval; - return ret; -} - -/*****************************************************************************/ -/* - * do the futex operations - */ -int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) -{ - int op = (encoded_op >> 28) & 7; - int cmp = (encoded_op >> 24) & 15; - int oparg = (encoded_op << 8) >> 20; - int cmparg = (encoded_op << 20) >> 20; - int oldval = 0, ret; - - if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) - oparg = 1 << oparg; - - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - - inc_preempt_count(); - - switch (op) { - case FUTEX_OP_SET: - ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval); - break; - case FUTEX_OP_ADD: - ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval); - break; - case FUTEX_OP_OR: - ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval); - break; - case FUTEX_OP_ANDN: - ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval); - break; - case FUTEX_OP_XOR: - ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval); - break; - default: - ret = -ENOSYS; - break; - } - - dec_preempt_count(); - - if (!ret) { - switch (cmp) { - case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; - case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; - case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; - case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; - case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; - case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; - default: ret = -ENOSYS; break; - } - } - - return ret; - -} /* end futex_atomic_op_inuser() */ diff --git a/trunk/arch/frv/kernel/signal.c b/trunk/arch/frv/kernel/signal.c index 5b7146f54fd5..d4ccc0728dfe 100644 --- a/trunk/arch/frv/kernel/signal.c +++ b/trunk/arch/frv/kernel/signal.c @@ -35,7 +35,7 @@ struct fdpic_func_descriptor { unsigned long GOT; }; -static int do_signal(sigset_t *oldset); +asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); /* * Atomically swap in the new signal mask, and wait for a signal. @@ -55,7 +55,7 @@ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&saveset)) + if (do_signal(__frame, &saveset)) /* return the signal number as the return value of this function * - this is an utterly evil hack. syscalls should not invoke do_signal() * as entry.S sets regs->gr8 to the return value of the system call @@ -91,7 +91,7 @@ asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&saveset)) + if (do_signal(__frame, &saveset)) /* return the signal number as the return value of this function * - this is an utterly evil hack. syscalls should not invoke do_signal() * as entry.S sets regs->gr8 to the return value of the system call @@ -276,12 +276,13 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask) * Determine which stack to use.. */ static inline void __user *get_sigframe(struct k_sigaction *ka, + struct pt_regs *regs, size_t frame_size) { unsigned long sp; /* Default to using normal stack */ - sp = __frame->sp; + sp = regs->sp; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { @@ -290,19 +291,18 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, } return (void __user *) ((sp - frame_size) & ~7UL); - } /* end get_sigframe() */ /*****************************************************************************/ /* * */ -static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) +static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs) { struct sigframe __user *frame; int rsig; - frame = get_sigframe(ka, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -346,51 +346,47 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) } /* set up registers for signal handler */ - __frame->sp = (unsigned long) frame; - __frame->lr = (unsigned long) &frame->retcode; - __frame->gr8 = sig; + regs->sp = (unsigned long) frame; + regs->lr = (unsigned long) &frame->retcode; + regs->gr8 = sig; if (get_personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor *) ka->sa.sa_handler; - __get_user(__frame->pc, &funcptr->text); - __get_user(__frame->gr15, &funcptr->GOT); + __get_user(regs->pc, &funcptr->text); + __get_user(regs->gr15, &funcptr->GOT); } else { - __frame->pc = (unsigned long) ka->sa.sa_handler; - __frame->gr15 = 0; + regs->pc = (unsigned long) ka->sa.sa_handler; + regs->gr15 = 0; } set_fs(USER_DS); - /* the tracer may want to single-step inside the handler */ - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); - #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", - sig, current->comm, current->pid, frame, __frame->pc, - frame->pretcode); + sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); #endif - return 1; + return; give_sigsegv: - force_sig(SIGSEGV, current); - return 0; + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } /* end setup_frame() */ /*****************************************************************************/ /* * */ -static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set) +static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs * regs) { struct rt_sigframe __user *frame; int rsig; - frame = get_sigframe(ka, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -413,7 +409,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (__put_user(0, &frame->uc.uc_flags) || __put_user(0, &frame->uc.uc_link) || __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || - __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) || + __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) || __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) goto give_sigsegv; @@ -444,38 +440,34 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } /* Set up registers for signal handler */ - __frame->sp = (unsigned long) frame; - __frame->lr = (unsigned long) &frame->retcode; - __frame->gr8 = sig; - __frame->gr9 = (unsigned long) &frame->info; + regs->sp = (unsigned long) frame; + regs->lr = (unsigned long) &frame->retcode; + regs->gr8 = sig; + regs->gr9 = (unsigned long) &frame->info; if (get_personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; - __get_user(__frame->pc, &funcptr->text); - __get_user(__frame->gr15, &funcptr->GOT); + __get_user(regs->pc, &funcptr->text); + __get_user(regs->gr15, &funcptr->GOT); } else { - __frame->pc = (unsigned long) ka->sa.sa_handler; - __frame->gr15 = 0; + regs->pc = (unsigned long) ka->sa.sa_handler; + regs->gr15 = 0; } set_fs(USER_DS); - /* the tracer may want to single-step inside the handler */ - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); - #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", - sig, current->comm, current->pid, frame, __frame->pc, - frame->pretcode); + sig, current->comm, current->pid, frame, regs->pc, frame->pretcode); #endif - return 1; + return; give_sigsegv: + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); - return 0; } /* end setup_rt_frame() */ @@ -483,51 +475,43 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* * OK, we're invoking a handler */ -static int handle_signal(unsigned long sig, siginfo_t *info, - struct k_sigaction *ka, sigset_t *oldset) +static void handle_signal(unsigned long sig, siginfo_t *info, + struct k_sigaction *ka, sigset_t *oldset, + struct pt_regs *regs) { - int ret; - /* Are we from a system call? */ - if (in_syscall(__frame)) { + if (in_syscall(regs)) { /* If so, check system call restarting.. */ - switch (__frame->gr8) { + switch (regs->gr8) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: - __frame->gr8 = -EINTR; + regs->gr8 = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { - __frame->gr8 = -EINTR; + regs->gr8 = -EINTR; break; } - /* fallthrough */ case -ERESTARTNOINTR: - __frame->gr8 = __frame->orig_gr8; - __frame->pc -= 4; + regs->gr8 = regs->orig_gr8; + regs->pc -= 4; } } /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(sig, ka, info, oldset); + setup_rt_frame(sig, ka, info, oldset, regs); else - ret = setup_frame(sig, ka, oldset); - - if (ret) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } - - return ret; + setup_frame(sig, ka, oldset, regs); + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); + if (!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked, sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); } /* end handle_signal() */ /*****************************************************************************/ @@ -536,7 +520,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -static int do_signal(sigset_t *oldset) +int do_signal(struct pt_regs *regs, sigset_t *oldset) { struct k_sigaction ka; siginfo_t info; @@ -548,7 +532,7 @@ static int do_signal(sigset_t *oldset) * kernel mode. Just return without doing anything * if so. */ - if (!user_mode(__frame)) + if (!user_mode(regs)) return 1; if (try_to_freeze()) @@ -557,29 +541,30 @@ static int do_signal(sigset_t *oldset) if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, &ka, __frame, NULL); - if (signr > 0) - return handle_signal(signr, &info, &ka, oldset); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + if (signr > 0) { + handle_signal(signr, &info, &ka, oldset, regs); + return 1; + } -no_signal: + no_signal: /* Did we come from a system call? */ - if (__frame->syscallno >= 0) { + if (regs->syscallno >= 0) { /* Restart the system call - no handlers present */ - if (__frame->gr8 == -ERESTARTNOHAND || - __frame->gr8 == -ERESTARTSYS || - __frame->gr8 == -ERESTARTNOINTR) { - __frame->gr8 = __frame->orig_gr8; - __frame->pc -= 4; + if (regs->gr8 == -ERESTARTNOHAND || + regs->gr8 == -ERESTARTSYS || + regs->gr8 == -ERESTARTNOINTR) { + regs->gr8 = regs->orig_gr8; + regs->pc -= 4; } - if (__frame->gr8 == -ERESTART_RESTARTBLOCK){ - __frame->gr8 = __NR_restart_syscall; - __frame->pc -= 4; + if (regs->gr8 == -ERESTART_RESTARTBLOCK){ + regs->gr8 = __NR_restart_syscall; + regs->pc -= 4; } } return 0; - } /* end do_signal() */ /*****************************************************************************/ @@ -595,6 +580,6 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) /* deal with pending signal delivery */ if (thread_info_flags & _TIF_SIGPENDING) - do_signal(NULL); + do_signal(__frame, NULL); } /* end do_notify_resume() */ diff --git a/trunk/arch/i386/Kconfig b/trunk/arch/i386/Kconfig index 968fabd8723f..6004bb0795e0 100644 --- a/trunk/arch/i386/Kconfig +++ b/trunk/arch/i386/Kconfig @@ -464,6 +464,7 @@ config NUMA depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) + select SPARSEMEM_STATIC # Need comments to help the hapless user trying to turn on NUMA support comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support" @@ -492,10 +493,6 @@ config HAVE_ARCH_ALLOC_REMAP depends on NUMA default y -config ARCH_FLATMEM_ENABLE - def_bool y - depends on (ARCH_SELECT_MEMORY_MODEL && X86_PC) - config ARCH_DISCONTIGMEM_ENABLE def_bool y depends on NUMA @@ -506,8 +503,7 @@ config ARCH_DISCONTIGMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on (NUMA || (X86_PC && EXPERIMENTAL)) - select SPARSEMEM_STATIC + depends on NUMA config ARCH_SELECT_MEMORY_MODEL def_bool y diff --git a/trunk/arch/i386/Kconfig.cpu b/trunk/arch/i386/Kconfig.cpu index 79603b3471f9..53bbb3c008ee 100644 --- a/trunk/arch/i386/Kconfig.cpu +++ b/trunk/arch/i386/Kconfig.cpu @@ -39,7 +39,6 @@ config M386 - "Winchip-2" for IDT Winchip 2. - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. - "GeodeGX1" for Geode GX1 (Cyrix MediaGX). - - "Geode GX/LX" For AMD Geode GX and LX processors. - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above). @@ -172,11 +171,6 @@ config MGEODEGX1 help Select this for a Geode GX1 (Cyrix MediaGX) chip. -config MGEODE_LX - bool "Geode GX/LX" - help - Select this for AMD Geode GX and LX processors. - config MCYRIXIII bool "CyrixIII/VIA-C3" help @@ -226,8 +220,8 @@ config X86_XADD config X86_L1_CACHE_SHIFT int default "7" if MPENTIUM4 || X86_GENERIC - default "4" if X86_ELAN || M486 || M386 || MGEODEGX1 - default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX + default "4" if X86_ELAN || M486 || M386 + default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1 default "6" if MK7 || MK8 || MPENTIUMM config RWSEM_GENERIC_SPINLOCK @@ -296,12 +290,12 @@ config X86_INTEL_USERCOPY config X86_USE_PPRO_CHECKSUM bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON default y config X86_USE_3DNOW bool - depends on MCYRIXIII || MK7 || MGEODE_LX + depends on MCYRIXIII || MK7 default y config X86_OOSTORE diff --git a/trunk/arch/i386/Kconfig.debug b/trunk/arch/i386/Kconfig.debug index bf32ecc9ad04..c48b424dd640 100644 --- a/trunk/arch/i386/Kconfig.debug +++ b/trunk/arch/i386/Kconfig.debug @@ -42,16 +42,6 @@ config DEBUG_PAGEALLOC This results in a large slowdown, but helps to find certain types of memory corruptions. -config DEBUG_RODATA - bool "Write protect kernel read-only data structures" - depends on DEBUG_KERNEL - help - Mark the kernel read-only data as write-protected in the pagetables, - in order to catch accidental (and incorrect) writes to such const - data. This option may have a slight performance impact because a - portion of the kernel code won't be covered by a 2MB TLB anymore. - If in doubt, say "N". - config 4KSTACKS bool "Use 4Kb for kernel stacks instead of 8Kb" depends on DEBUG_KERNEL diff --git a/trunk/arch/i386/kernel/apic.c b/trunk/arch/i386/kernel/apic.c index d8f94e78de8a..496a2c9909fe 100644 --- a/trunk/arch/i386/kernel/apic.c +++ b/trunk/arch/i386/kernel/apic.c @@ -721,7 +721,7 @@ static int __init apic_set_verbosity(char *str) apic_verbosity = APIC_VERBOSE; else printk(KERN_WARNING "APIC Verbosity level %s not recognised" - " use apic=verbose or apic=debug\n", str); + " use apic=verbose or apic=debug", str); return 0; } diff --git a/trunk/arch/i386/kernel/apm.c b/trunk/arch/i386/kernel/apm.c index 2d793d4aef1a..1e60acbed3c1 100644 --- a/trunk/arch/i386/kernel/apm.c +++ b/trunk/arch/i386/kernel/apm.c @@ -302,6 +302,17 @@ extern int (*console_blank_hook)(int); #include "apm.h" +/* + * Define to make all _set_limit calls use 64k limits. The APM 1.1 BIOS is + * supposed to provide limit information that it recognizes. Many machines + * do this correctly, but many others do not restrict themselves to their + * claimed limit. When this happens, they will cause a segmentation + * violation in the kernel at boot time. Most BIOS's, however, will + * respect a 64k limit, so we use that. If you want to be pedantic and + * hold your BIOS to its claims, then undefine this. + */ +#define APM_RELAX_SEGMENTS + /* * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend. * This patched by Chad Miller , original code by @@ -1064,23 +1075,22 @@ static int apm_engage_power_management(u_short device, int enable) static int apm_console_blank(int blank) { - int error, i; - u_short state; - static const u_short dev[3] = { 0x100, 0x1FF, 0x101 }; + int error; + u_short state; state = blank ? APM_STATE_STANDBY : APM_STATE_READY; - - for (i = 0; i < ARRAY_SIZE(dev); i++) { - error = set_power_state(dev[i], state); - - if ((error == APM_SUCCESS) || (error == APM_NO_ERROR)) - return 1; - - if (error == APM_NOT_ENGAGED) - break; + /* Blank the first display device */ + error = set_power_state(0x100, state); + if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) { + /* try to blank them all instead */ + error = set_power_state(0x1ff, state); + if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) + /* try to blank device one instead */ + error = set_power_state(0x101, state); } - - if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) { + if ((error == APM_SUCCESS) || (error == APM_NO_ERROR)) + return 1; + if (error == APM_NOT_ENGAGED) { static int tried; int eng_error; if (tried++ == 0) { @@ -2223,8 +2233,8 @@ static struct dmi_system_id __initdata apm_dmi_table[] = { static int __init apm_init(void) { struct proc_dir_entry *apm_proc; - struct desc_struct *gdt; int ret; + int i; dmi_check_system(apm_dmi_table); @@ -2302,30 +2312,45 @@ static int __init apm_init(void) set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); - /* - * Set up the long jump entry point to the APM BIOS, which is called - * from inline assembly. - */ apm_bios_entry.offset = apm_info.bios.offset; apm_bios_entry.segment = APM_CS; - /* - * The APM 1.1 BIOS is supposed to provide limit information that it - * recognizes. Many machines do this correctly, but many others do - * not restrict themselves to their claimed limit. When this happens, - * they will cause a segmentation violation in the kernel at boot time. - * Most BIOS's, however, will respect a 64k limit, so we use that. - * - * Note we only set APM segments on CPU zero, since we pin the APM - * code to that CPU. - */ - gdt = get_cpu_gdt_table(0); - set_base(gdt[APM_CS >> 3], - __va((unsigned long)apm_info.bios.cseg << 4)); - set_base(gdt[APM_CS_16 >> 3], - __va((unsigned long)apm_info.bios.cseg_16 << 4)); - set_base(gdt[APM_DS >> 3], - __va((unsigned long)apm_info.bios.dseg << 4)); + for (i = 0; i < NR_CPUS; i++) { + struct desc_struct *gdt = get_cpu_gdt_table(i); + set_base(gdt[APM_CS >> 3], + __va((unsigned long)apm_info.bios.cseg << 4)); + set_base(gdt[APM_CS_16 >> 3], + __va((unsigned long)apm_info.bios.cseg_16 << 4)); + set_base(gdt[APM_DS >> 3], + __va((unsigned long)apm_info.bios.dseg << 4)); +#ifndef APM_RELAX_SEGMENTS + if (apm_info.bios.version == 0x100) { +#endif + /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ + _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1); + /* For some unknown machine. */ + _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1); + /* For the DEC Hinote Ultra CT475 (and others?) */ + _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1); +#ifndef APM_RELAX_SEGMENTS + } else { + _set_limit((char *)&gdt[APM_CS >> 3], + (apm_info.bios.cseg_len - 1) & 0xffff); + _set_limit((char *)&gdt[APM_CS_16 >> 3], + (apm_info.bios.cseg_16_len - 1) & 0xffff); + _set_limit((char *)&gdt[APM_DS >> 3], + (apm_info.bios.dseg_len - 1) & 0xffff); + /* workaround for broken BIOSes */ + if (apm_info.bios.cseg_len <= apm_info.bios.offset) + _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 -1); + if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */ + /* for the BIOS that assumes granularity = 1 */ + gdt[APM_DS >> 3].b |= 0x800000; + printk(KERN_NOTICE "apm: we set the granularity of dseg.\n"); + } + } +#endif + } apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); if (apm_proc) diff --git a/trunk/arch/i386/kernel/cpu/amd.c b/trunk/arch/i386/kernel/cpu/amd.c index e7697e077f6b..e344ef88cfcd 100644 --- a/trunk/arch/i386/kernel/cpu/amd.c +++ b/trunk/arch/i386/kernel/cpu/amd.c @@ -161,13 +161,8 @@ static void __init init_amd(struct cpuinfo_x86 *c) set_bit(X86_FEATURE_K6_MTRR, c->x86_capability); break; } - - if (c->x86_model == 10) { - /* AMD Geode LX is model 10 */ - /* placeholder for any needed mods */ - break; - } break; + case 6: /* An Athlon/Duron */ /* Bit 15 of Athlon specific MSR 15, needs to be 0 diff --git a/trunk/arch/i386/kernel/cpu/common.c b/trunk/arch/i386/kernel/cpu/common.c index cca655688ffc..31e344b26bae 100644 --- a/trunk/arch/i386/kernel/cpu/common.c +++ b/trunk/arch/i386/kernel/cpu/common.c @@ -18,6 +18,9 @@ #include "cpu.h" +DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]); +EXPORT_PER_CPU_SYMBOL(cpu_gdt_table); + DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); @@ -595,6 +598,11 @@ void __devinit cpu_init(void) load_gdt(&cpu_gdt_descr[cpu]); load_idt(&idt_descr); + /* + * Delete NT + */ + __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); + /* * Set up and load the per-CPU TSS and LDT */ diff --git a/trunk/arch/i386/kernel/cpu/cyrix.c b/trunk/arch/i386/kernel/cpu/cyrix.c index 75015975d038..ff87cc22b323 100644 --- a/trunk/arch/i386/kernel/cpu/cyrix.c +++ b/trunk/arch/i386/kernel/cpu/cyrix.c @@ -342,31 +342,6 @@ static void __init init_cyrix(struct cpuinfo_x86 *c) return; } -/* - * Handle National Semiconductor branded processors - */ -static void __devinit init_nsc(struct cpuinfo_x86 *c) -{ - /* There may be GX1 processors in the wild that are branded - * NSC and not Cyrix. - * - * This function only handles the GX processor, and kicks every - * thing else to the Cyrix init function above - that should - * cover any processors that might have been branded differently - * after NSC aquired Cyrix. - * - * If this breaks your GX1 horribly, please e-mail - * info-linux@ldcmail.amd.com to tell us. - */ - - /* Handle the GX (Formally known as the GX2) */ - - if (c->x86 == 5 && c->x86_model == 5) - display_cacheinfo(c); - else - init_cyrix(c); -} - /* * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected * by the fact that they preserve the flags across the division of 5/2. @@ -447,7 +422,7 @@ int __init cyrix_init_cpu(void) static struct cpu_dev nsc_cpu_dev __initdata = { .c_vendor = "NSC", .c_ident = { "Geode by NSC" }, - .c_init = init_nsc, + .c_init = init_cyrix, .c_identify = generic_identify, }; diff --git a/trunk/arch/i386/kernel/cpuid.c b/trunk/arch/i386/kernel/cpuid.c index 006141d1c12a..13bae799e626 100644 --- a/trunk/arch/i386/kernel/cpuid.c +++ b/trunk/arch/i386/kernel/cpuid.c @@ -117,13 +117,14 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, { char __user *tmp = buf; u32 data[4]; + size_t rv; u32 reg = *ppos; int cpu = iminor(file->f_dentry->d_inode); if (count % 16) return -EINVAL; /* Invalid chunk size */ - for (; count; count -= 16) { + for (rv = 0; count; count -= 16) { do_cpuid(cpu, reg, data); if (copy_to_user(tmp, &data, 16)) return -EFAULT; diff --git a/trunk/arch/i386/kernel/entry.S b/trunk/arch/i386/kernel/entry.S index 607c06007508..e50b93155249 100644 --- a/trunk/arch/i386/kernel/entry.S +++ b/trunk/arch/i386/kernel/entry.S @@ -657,7 +657,6 @@ ENTRY(spurious_interrupt_bug) pushl $do_spurious_interrupt_bug jmp error_code -.section .rodata,"a" #include "syscall_table.S" syscall_table_size=(.-sys_call_table) diff --git a/trunk/arch/i386/kernel/head.S b/trunk/arch/i386/kernel/head.S index 5884469f6bfe..e437fb367498 100644 --- a/trunk/arch/i386/kernel/head.S +++ b/trunk/arch/i386/kernel/head.S @@ -504,24 +504,19 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0x80 TSS descriptor */ .quad 0x0000000000000000 /* 0x88 LDT descriptor */ - /* - * Segments used for calling PnP BIOS have byte granularity. - * They code segments and data segments have fixed 64k limits, - * the transfer segment sizes are set at run time. - */ - .quad 0x00409a000000ffff /* 0x90 32-bit code */ - .quad 0x00009a000000ffff /* 0x98 16-bit code */ - .quad 0x000092000000ffff /* 0xa0 16-bit data */ - .quad 0x0000920000000000 /* 0xa8 16-bit data */ - .quad 0x0000920000000000 /* 0xb0 16-bit data */ - + /* Segments used for calling PnP BIOS */ + .quad 0x00c09a0000000000 /* 0x90 32-bit code */ + .quad 0x00809a0000000000 /* 0x98 16-bit code */ + .quad 0x0080920000000000 /* 0xa0 16-bit data */ + .quad 0x0080920000000000 /* 0xa8 16-bit data */ + .quad 0x0080920000000000 /* 0xb0 16-bit data */ /* * The APM segments have byte granularity and their bases - * are set at run time. All have 64k limits. + * and limits are set at run time. */ - .quad 0x00409a000000ffff /* 0xb8 APM CS code */ - .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */ - .quad 0x004092000000ffff /* 0xc8 APM DS data */ + .quad 0x00409a0000000000 /* 0xb8 APM CS code */ + .quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */ + .quad 0x0040920000000000 /* 0xc8 APM DS data */ .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */ .quad 0x0000000000000000 /* 0xd8 - unused */ @@ -530,5 +525,3 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0xf0 - unused */ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ - /* Be sure this is zeroed to avoid false validations in Xen */ - .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0 diff --git a/trunk/arch/i386/kernel/i386_ksyms.c b/trunk/arch/i386/kernel/i386_ksyms.c index 3999bec50c33..180f070d03cb 100644 --- a/trunk/arch/i386/kernel/i386_ksyms.c +++ b/trunk/arch/i386/kernel/i386_ksyms.c @@ -3,7 +3,8 @@ #include #include -EXPORT_SYMBOL_GPL(cpu_gdt_descr); +/* This is definitely a GPL-only symbol */ +EXPORT_SYMBOL_GPL(cpu_gdt_table); EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); diff --git a/trunk/arch/i386/kernel/io_apic.c b/trunk/arch/i386/kernel/io_apic.c index 7554f8fd874a..22c8675c79f4 100644 --- a/trunk/arch/i386/kernel/io_apic.c +++ b/trunk/arch/i386/kernel/io_apic.c @@ -1722,8 +1722,8 @@ void disable_IO_APIC(void) entry.dest_mode = 0; /* Physical */ entry.delivery_mode = dest_ExtINT; /* ExtInt */ entry.vector = 0; - entry.dest.physical.physical_dest = - GET_APIC_ID(apic_read(APIC_ID)); + entry.dest.physical.physical_dest = 0; + /* * Add it to the IO-APIC irq-routing table: diff --git a/trunk/arch/i386/kernel/mpparse.c b/trunk/arch/i386/kernel/mpparse.c index 91a64016956e..1ca5269b1e86 100644 --- a/trunk/arch/i386/kernel/mpparse.c +++ b/trunk/arch/i386/kernel/mpparse.c @@ -38,12 +38,6 @@ int smp_found_config; unsigned int __initdata maxcpus = NR_CPUS; -#ifdef CONFIG_HOTPLUG_CPU -#define CPU_HOTPLUG_ENABLED (1) -#else -#define CPU_HOTPLUG_ENABLED (0) -#endif - /* * Various Linux-internal data structures created from the * MP-table. @@ -225,18 +219,14 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m) cpu_set(num_processors, cpu_possible_map); num_processors++; - if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) { - switch (boot_cpu_data.x86_vendor) { - case X86_VENDOR_INTEL: - if (!APIC_XAPIC(ver)) { - def_to_bigsmp = 0; - break; - } - /* If P4 and above fall through */ - case X86_VENDOR_AMD: - def_to_bigsmp = 1; - } - } + if ((num_processors > 8) && + ((APIC_XAPIC(ver) && + (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)) || + (boot_cpu_data.x86_vendor == X86_VENDOR_AMD))) + def_to_bigsmp = 1; + else + def_to_bigsmp = 0; + bios_cpu_apicid[num_processors - 1] = m->mpc_apicid; } diff --git a/trunk/arch/i386/kernel/msr.c b/trunk/arch/i386/kernel/msr.c index 1d0a55e68760..44470fea4309 100644 --- a/trunk/arch/i386/kernel/msr.c +++ b/trunk/arch/i386/kernel/msr.c @@ -172,6 +172,7 @@ static ssize_t msr_read(struct file *file, char __user * buf, { u32 __user *tmp = (u32 __user *) buf; u32 data[2]; + size_t rv; u32 reg = *ppos; int cpu = iminor(file->f_dentry->d_inode); int err; @@ -179,7 +180,7 @@ static ssize_t msr_read(struct file *file, char __user * buf, if (count % 8) return -EINVAL; /* Invalid chunk size */ - for (; count; count -= 8) { + for (rv = 0; count; count -= 8) { err = do_rdmsr(cpu, reg, &data[0], &data[1]); if (err) return err; diff --git a/trunk/arch/i386/kernel/process.c b/trunk/arch/i386/kernel/process.c index 45e7f0ac4b04..2333aead0563 100644 --- a/trunk/arch/i386/kernel/process.c +++ b/trunk/arch/i386/kernel/process.c @@ -308,7 +308,9 @@ void show_regs(struct pt_regs * regs) cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); - cr4 = read_cr4_safe(); + if (current_cpu_data.x86 > 4) { + cr4 = read_cr4(); + } printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); show_trace(NULL, ®s->esp); } @@ -402,7 +404,17 @@ void flush_thread(void) void release_thread(struct task_struct *dead_task) { - BUG_ON(dead_task->mm); + if (dead_task->mm) { + // temporary debugging check + if (dead_task->mm->context.size) { + printk("WARNING: dead process %8s still has LDT? <%p/%d>\n", + dead_task->comm, + dead_task->mm->context.ldt, + dead_task->mm->context.size); + BUG(); + } + } + release_vm86_irqs(dead_task); } diff --git a/trunk/arch/i386/kernel/reboot.c b/trunk/arch/i386/kernel/reboot.c index 2fa5803a759d..2afe0f8d555a 100644 --- a/trunk/arch/i386/kernel/reboot.c +++ b/trunk/arch/i386/kernel/reboot.c @@ -111,12 +111,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"), }, }, - { /* Handle problems with rebooting on HP laptops */ + { /* Handle problems with rebooting on HP nc6120 */ .callback = set_bios_reboot, - .ident = "HP Compaq Laptop", + .ident = "HP Compaq nc6120", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6120"), }, }, { } diff --git a/trunk/arch/i386/kernel/setup.c b/trunk/arch/i386/kernel/setup.c index 27c956db0461..fdfcb0cba9b4 100644 --- a/trunk/arch/i386/kernel/setup.c +++ b/trunk/arch/i386/kernel/setup.c @@ -954,12 +954,6 @@ efi_find_max_pfn(unsigned long start, unsigned long end, void *arg) return 0; } -static int __init -efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) -{ - memory_present(0, start, end); - return 0; -} /* * Find the highest page frame number we have available @@ -971,7 +965,6 @@ void __init find_max_pfn(void) max_pfn = 0; if (efi_enabled) { efi_memmap_walk(efi_find_max_pfn, &max_pfn); - efi_memmap_walk(efi_memory_present_wrapper, NULL); return; } @@ -986,7 +979,6 @@ void __init find_max_pfn(void) continue; if (end > max_pfn) max_pfn = end; - memory_present(0, start, end); } } diff --git a/trunk/arch/i386/kernel/smpboot.c b/trunk/arch/i386/kernel/smpboot.c index b3c2e2c26743..9ed449af8e9f 100644 --- a/trunk/arch/i386/kernel/smpboot.c +++ b/trunk/arch/i386/kernel/smpboot.c @@ -903,12 +903,6 @@ static int __devinit do_boot_cpu(int apicid, int cpu) unsigned long start_eip; unsigned short nmi_high = 0, nmi_low = 0; - if (!cpu_gdt_descr[cpu].address && - !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) { - printk("Failed to allocate GDT for CPU %d\n", cpu); - return 1; - } - ++cpucount; /* diff --git a/trunk/arch/i386/kernel/syscall_table.S b/trunk/arch/i386/kernel/syscall_table.S index f7ba4acc20ec..9b21a31d4f4e 100644 --- a/trunk/arch/i386/kernel/syscall_table.S +++ b/trunk/arch/i386/kernel/syscall_table.S @@ -1,3 +1,4 @@ +.data ENTRY(sys_call_table) .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ .long sys_exit diff --git a/trunk/arch/i386/kernel/timers/timer_tsc.c b/trunk/arch/i386/kernel/timers/timer_tsc.c index 47675bbbb316..d395e3b42485 100644 --- a/trunk/arch/i386/kernel/timers/timer_tsc.c +++ b/trunk/arch/i386/kernel/timers/timer_tsc.c @@ -330,9 +330,7 @@ int recalibrate_cpu_khz(void) unsigned int cpu_khz_old = cpu_khz; if (cpu_has_tsc) { - local_irq_disable(); init_cpu_khz(); - local_irq_enable(); cpu_data[0].loops_per_jiffy = cpufreq_scale(cpu_data[0].loops_per_jiffy, cpu_khz_old, diff --git a/trunk/arch/i386/kernel/traps.c b/trunk/arch/i386/kernel/traps.c index 53ad954e3ba4..ab0e9430f775 100644 --- a/trunk/arch/i386/kernel/traps.c +++ b/trunk/arch/i386/kernel/traps.c @@ -306,17 +306,14 @@ void die(const char * str, struct pt_regs * regs, long err) .lock_owner_depth = 0 }; static int die_counter; - unsigned long flags; if (die.lock_owner != raw_smp_processor_id()) { console_verbose(); - spin_lock_irqsave(&die.lock, flags); + spin_lock_irq(&die.lock); die.lock_owner = smp_processor_id(); die.lock_owner_depth = 0; bust_spinlocks(1); } - else - local_save_flags(flags); if (++die.lock_owner_depth < 3) { int nl = 0; @@ -343,7 +340,7 @@ void die(const char * str, struct pt_regs * regs, long err) bust_spinlocks(0); die.lock_owner = -1; - spin_unlock_irqrestore(&die.lock, flags); + spin_unlock_irq(&die.lock); if (kexec_should_crash(current)) crash_kexec(regs); @@ -1078,9 +1075,9 @@ void __init trap_init(void) set_trap_gate(0,÷_error); set_intr_gate(1,&debug); set_intr_gate(2,&nmi); - set_system_intr_gate(3, &int3); /* int3/4 can be called from all */ + set_system_intr_gate(3, &int3); /* int3-5 can be called from all */ set_system_gate(4,&overflow); - set_trap_gate(5,&bounds); + set_system_gate(5,&bounds); set_trap_gate(6,&invalid_op); set_trap_gate(7,&device_not_available); set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS); @@ -1098,28 +1095,6 @@ void __init trap_init(void) #endif set_trap_gate(19,&simd_coprocessor_error); - if (cpu_has_fxsr) { - /* - * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned. - * Generates a compile-time "error: zero width for bit-field" if - * the alignment is wrong. - */ - struct fxsrAlignAssert { - int _:!(offsetof(struct task_struct, - thread.i387.fxsave) & 15); - }; - - printk(KERN_INFO "Enabling fast FPU save and restore... "); - set_in_cr4(X86_CR4_OSFXSR); - printk("done.\n"); - } - if (cpu_has_xmm) { - printk(KERN_INFO "Enabling unmasked SIMD FPU exception " - "support... "); - set_in_cr4(X86_CR4_OSXMMEXCPT); - printk("done.\n"); - } - set_system_gate(SYSCALL_VECTOR,&system_call); /* diff --git a/trunk/arch/i386/mm/init.c b/trunk/arch/i386/mm/init.c index 7df494b51a5b..06e26f006238 100644 --- a/trunk/arch/i386/mm/init.c +++ b/trunk/arch/i386/mm/init.c @@ -735,30 +735,6 @@ void free_initmem(void) printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10); } -#ifdef CONFIG_DEBUG_RODATA - -extern char __start_rodata, __end_rodata; -void mark_rodata_ro(void) -{ - unsigned long addr = (unsigned long)&__start_rodata; - - for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE) - change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO); - - printk ("Write protecting the kernel read-only data: %luk\n", - (unsigned long)(&__end_rodata - &__start_rodata) >> 10); - - /* - * change_page_attr() requires a global_flush_tlb() call after it. - * We do this after the printk so that if something went wrong in the - * change, the printk gets out at least to give a better debug hint - * of who is the culprit. - */ - global_flush_tlb(); -} -#endif - - #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { diff --git a/trunk/arch/i386/mm/pageattr.c b/trunk/arch/i386/mm/pageattr.c index c30a16df6440..f600fc244f02 100644 --- a/trunk/arch/i386/mm/pageattr.c +++ b/trunk/arch/i386/mm/pageattr.c @@ -13,7 +13,6 @@ #include #include #include -#include static DEFINE_SPINLOCK(cpa_lock); static struct list_head df_list = LIST_HEAD_INIT(df_list); @@ -37,8 +36,7 @@ pte_t *lookup_address(unsigned long address) return pte_offset_kernel(pmd, address); } -static struct page *split_large_page(unsigned long address, pgprot_t prot, - pgprot_t ref_prot) +static struct page *split_large_page(unsigned long address, pgprot_t prot) { int i; unsigned long addr; @@ -56,7 +54,7 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot, pbase = (pte_t *)page_address(base); for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) { set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, - addr == address ? prot : ref_prot)); + addr == address ? prot : PAGE_KERNEL)); } return base; } @@ -100,18 +98,11 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) */ static inline void revert_page(struct page *kpte_page, unsigned long address) { - pgprot_t ref_prot; - pte_t *linear; - - ref_prot = - ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext) - ? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE; - - linear = (pte_t *) + pte_t *linear = (pte_t *) pmd_offset(pud_offset(pgd_offset_k(address), address), address); set_pmd_pte(linear, address, pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT, - ref_prot)); + PAGE_KERNEL_LARGE)); } static int @@ -132,16 +123,10 @@ __change_page_attr(struct page *page, pgprot_t prot) if ((pte_val(*kpte) & _PAGE_PSE) == 0) { set_pte_atomic(kpte, mk_pte(page, prot)); } else { - pgprot_t ref_prot; - struct page *split; - - ref_prot = - ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext) - ? PAGE_KERNEL_EXEC : PAGE_KERNEL; - split = split_large_page(address, prot, ref_prot); + struct page *split = split_large_page(address, prot); if (!split) return -ENOMEM; - set_pmd_pte(kpte,address,mk_pte(split, ref_prot)); + set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL)); kpte_page = split; } get_page(kpte_page); diff --git a/trunk/arch/i386/pci/irq.c b/trunk/arch/i386/pci/irq.c index ee8e01697d96..19e6f4871d1e 100644 --- a/trunk/arch/i386/pci/irq.c +++ b/trunk/arch/i386/pci/irq.c @@ -846,7 +846,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) * reported by the device if possible. */ newirq = dev->irq; - if (newirq && !((1 << newirq) & mask)) { + if (!((1 << newirq) & mask)) { if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0; else printk(KERN_WARNING "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n", newirq, pci_name(dev)); } diff --git a/trunk/arch/m32r/Kconfig b/trunk/arch/m32r/Kconfig index fae67bbb52f6..4d100f3886e1 100644 --- a/trunk/arch/m32r/Kconfig +++ b/trunk/arch/m32r/Kconfig @@ -81,12 +81,6 @@ config PLAT_MAPPI2 config PLAT_MAPPI3 bool "Mappi-III(M3A-2170)" -config PLAT_M32104UT - bool "M32104UT" - help - The M3T-M32104UT is an reference board based on uT-Engine - specification. This board has a M32104 chip. - endchoice choice @@ -99,10 +93,6 @@ config CHIP_M32700 config CHIP_M32102 bool "M32102" -config CHIP_M32104 - bool "M32104" - depends on PLAT_M32104UT - config CHIP_VDEC2 bool "VDEC2" @@ -125,7 +115,7 @@ config TLB_ENTRIES config ISA_M32R bool - depends on CHIP_M32102 || CHIP_M32104 + depends on CHIP_M32102 default y config ISA_M32R2 @@ -150,7 +140,6 @@ config BUS_CLOCK default "50000000" if PLAT_MAPPI3 default "50000000" if PLAT_M32700UT default "50000000" if PLAT_OPSPUT - default "54000000" if PLAT_M32104UT default "33333333" if PLAT_OAKS32R default "20000000" if PLAT_MAPPI2 @@ -168,7 +157,6 @@ config MEMORY_START default "08000000" if PLAT_USRV default "08000000" if PLAT_M32700UT default "08000000" if PLAT_OPSPUT - default "04000000" if PLAT_M32104UT default "01000000" if PLAT_OAKS32R config MEMORY_SIZE @@ -178,7 +166,6 @@ config MEMORY_SIZE default "02000000" if PLAT_USRV default "01000000" if PLAT_M32700UT default "01000000" if PLAT_OPSPUT - default "01000000" if PLAT_M32104UT default "00800000" if PLAT_OAKS32R config NOHIGHMEM @@ -187,22 +174,21 @@ config NOHIGHMEM config ARCH_DISCONTIGMEM_ENABLE bool "Internal RAM Support" - depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104 + depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP default y source "mm/Kconfig" config IRAM_START hex "Internal memory start address (hex)" - default "00f00000" if !CHIP_M32104 - default "00700000" if CHIP_M32104 - depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104) && DISCONTIGMEM + default "00f00000" + depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM config IRAM_SIZE hex "Internal memory size (hex)" - depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104) && DISCONTIGMEM + depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM default "00080000" if CHIP_M32700 - default "00010000" if CHIP_M32102 || CHIP_OPSP || CHIP_M32104 + default "00010000" if CHIP_M32102 || CHIP_OPSP default "00008000" if CHIP_VDEC2 # diff --git a/trunk/arch/m32r/boot/compressed/head.S b/trunk/arch/m32r/boot/compressed/head.S index 234d8b1e0ac1..07cfd6ad1ae4 100644 --- a/trunk/arch/m32r/boot/compressed/head.S +++ b/trunk/arch/m32r/boot/compressed/head.S @@ -143,11 +143,6 @@ startup: ldi r0, -2 ldi r1, 0x0100 ; invalidate stb r1, @r0 -#elif defined(CONFIG_CHIP_M32104) - /* Cache flush */ - ldi r0, -2 - ldi r1, 0x0700 ; invalidate i-cache, copy back d-cache - sth r1, @r0 #else #error "put your cache flush function, please" #endif diff --git a/trunk/arch/m32r/boot/setup.S b/trunk/arch/m32r/boot/setup.S index 398542507d84..5d256434b4ad 100644 --- a/trunk/arch/m32r/boot/setup.S +++ b/trunk/arch/m32r/boot/setup.S @@ -1,10 +1,11 @@ /* * linux/arch/m32r/boot/setup.S -- A setup code. * - * Copyright (C) 2001-2005 Hiroyuki Kondo, Hirokazu Takata, - * Hitoshi Yamamoto, Hayato Fujiwara + * Copyright (C) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata, + * and Hitoshi Yamamoto * */ +/* $Id$ */ #include #include @@ -79,20 +80,6 @@ ENTRY(boot) ldi r1, #0x101 ; cache on (with invalidation) ; ldi r1, #0x00 ; cache off st r1, @r0 -#elif defined(CONFIG_CHIP_M32104) - ldi r0, #-96 ; DNCR0 - seth r1, #0x0060 ; from 0x00600000 - or3 r1, r1, #0x0005 ; size 2MB - st r1, @r0 - seth r1, #0x0100 ; from 0x01000000 - or3 r1, r1, #0x0003 ; size 16MB - st r1, @+r0 - seth r1, #0x0200 ; from 0x02000000 - or3 r1, r1, #0x0002 ; size 32MB - st r1, @+r0 - ldi r0, #-4 ;LDIMM (r0, M32R_MCCR) - ldi r1, #0x703 ; cache on (with invalidation) - st r1, @r0 #else #error unknown chip configuration #endif @@ -128,15 +115,10 @@ mmu_on: st r1, @(MATM_offset,r0) ; Set MATM (T bit ON) ld r0, @(MATM_offset,r0) ; Check #else -#if defined(CONFIG_CHIP_M32700) seth r0,#high(M32R_MCDCAR) or3 r0,r0,#low(M32R_MCDCAR) ld24 r1,#0x8080 st r1,@r0 -#elif defined(CONFIG_CHIP_M32104) - LDIMM (r2, eit_vector) ; set EVB(cr5) - mvtc r2, cr5 -#endif #endif /* CONFIG_MMU */ jmp r13 nop diff --git a/trunk/arch/m32r/kernel/Makefile b/trunk/arch/m32r/kernel/Makefile index 5a2fa886906f..6c6b6c376638 100644 --- a/trunk/arch/m32r/kernel/Makefile +++ b/trunk/arch/m32r/kernel/Makefile @@ -16,6 +16,5 @@ obj-$(CONFIG_PLAT_M32700UT) += setup_m32700ut.o io_m32700ut.o obj-$(CONFIG_PLAT_OPSPUT) += setup_opsput.o io_opsput.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_PLAT_OAKS32R) += setup_oaks32r.o io_oaks32r.o -obj-$(CONFIG_PLAT_M32104UT) += setup_m32104ut.o io_m32104ut.o EXTRA_AFLAGS := -traditional diff --git a/trunk/arch/m32r/kernel/entry.S b/trunk/arch/m32r/kernel/entry.S index 3871b65f0c82..396c94218cc2 100644 --- a/trunk/arch/m32r/kernel/entry.S +++ b/trunk/arch/m32r/kernel/entry.S @@ -315,7 +315,7 @@ ENTRY(ei_handler) mv r1, sp ; arg1(regs) #if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \ - || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) + || defined(CONFIG_CHIP_OPSP) ; GET_ICU_STATUS; seth r0, #shigh(M32R_ICU_ISTS_ADDR) @@ -541,20 +541,7 @@ check_int2: bra check_end .fillinsn check_end: -#elif defined(CONFIG_PLAT_M32104UT) - add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt - bnez r2, check_end - ; read ICU status register of PLD - seth r0, #high(PLD_ICUISTS) - or3 r0, r0, #low(PLD_ICUISTS) - lduh r0, @r0 - slli r0, #21 - srli r0, #27 ; ISN - addi r0, #(M32104UT_PLD_IRQ_BASE) - bra check_end - .fillinsn -check_end: -#endif /* CONFIG_PLAT_M32104UT */ +#endif /* CONFIG_PLAT_OPSPUT */ bl do_IRQ #endif /* CONFIG_SMP */ ld r14, @sp+ @@ -664,6 +651,8 @@ ENTRY(rie_handler) /* void rie_handler(int error_code) */ SWITCH_TO_KERNEL_STACK SAVE_ALL + mvfc r0, bpc + ld r1, @r0 ldi r1, #0x20 ; error_code mv r0, sp ; pt_regs bl do_rie_handler diff --git a/trunk/arch/m32r/kernel/io_m32104ut.c b/trunk/arch/m32r/kernel/io_m32104ut.c deleted file mode 100644 index d26adab9586c..000000000000 --- a/trunk/arch/m32r/kernel/io_m32104ut.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - * linux/arch/m32r/kernel/io_m32104ut.c - * - * Typical I/O routines for M32104UT board. - * - * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata, - * Hitoshi Yamamoto, Mamoru Sakugawa, - * Naoto Sugai, Hayato Fujiwara - */ - -#include -#include -#include -#include -#include - -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) -#include - -#define M32R_PCC_IOMAP_SIZE 0x1000 - -#define M32R_PCC_IOSTART0 0x1000 -#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1) - -extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int); -extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int); -extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int); -extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); -#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */ - -#define PORT2ADDR(port) _port2addr(port) - -static inline void *_port2addr(unsigned long port) -{ - return (void *)(port | NONCACHE_OFFSET); -} - -#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) -static inline void *__port2addr_ata(unsigned long port) -{ - static int dummy_reg; - - switch (port) { - case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET); - case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET); - case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET); - case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET); - case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET); - case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET); - case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET); - case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET); - case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET); - default: return (void *)&dummy_reg; - } -} -#endif - -/* - * M32104T-LAN is located in the extended bus space - * from 0x01000000 to 0x01ffffff on physical address. - * The base address of LAN controller(LAN91C111) is 0x300. - */ -#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) -#define LAN_IOEND (0x320 | NONCACHE_OFFSET) -static inline void *_port2addr_ne(unsigned long port) -{ - return (void *)(port + NONCACHE_OFFSET + 0x01000000); -} - -static inline void delay(void) -{ - __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory"); -} - -/* - * NIC I/O function - */ - -#define PORT2ADDR_NE(port) _port2addr_ne(port) - -static inline unsigned char _ne_inb(void *portp) -{ - return *(volatile unsigned char *)portp; -} - -static inline unsigned short _ne_inw(void *portp) -{ - return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp); -} - -static inline void _ne_insb(void *portp, void *addr, unsigned long count) -{ - unsigned char *buf = (unsigned char *)addr; - - while (count--) - *buf++ = _ne_inb(portp); -} - -static inline void _ne_outb(unsigned char b, void *portp) -{ - *(volatile unsigned char *)portp = b; -} - -static inline void _ne_outw(unsigned short w, void *portp) -{ - *(volatile unsigned short *)portp = cpu_to_le16(w); -} - -unsigned char _inb(unsigned long port) -{ - if (port >= LAN_IOSTART && port < LAN_IOEND) - return _ne_inb(PORT2ADDR_NE(port)); - - return *(volatile unsigned char *)PORT2ADDR(port); -} - -unsigned short _inw(unsigned long port) -{ - if (port >= LAN_IOSTART && port < LAN_IOEND) - return _ne_inw(PORT2ADDR_NE(port)); - - return *(volatile unsigned short *)PORT2ADDR(port); -} - -unsigned long _inl(unsigned long port) -{ - return *(volatile unsigned long *)PORT2ADDR(port); -} - -unsigned char _inb_p(unsigned long port) -{ - unsigned char v = _inb(port); - delay(); - return (v); -} - -unsigned short _inw_p(unsigned long port) -{ - unsigned short v = _inw(port); - delay(); - return (v); -} - -unsigned long _inl_p(unsigned long port) -{ - unsigned long v = _inl(port); - delay(); - return (v); -} - -void _outb(unsigned char b, unsigned long port) -{ - if (port >= LAN_IOSTART && port < LAN_IOEND) - _ne_outb(b, PORT2ADDR_NE(port)); - else - *(volatile unsigned char *)PORT2ADDR(port) = b; -} - -void _outw(unsigned short w, unsigned long port) -{ - if (port >= LAN_IOSTART && port < LAN_IOEND) - _ne_outw(w, PORT2ADDR_NE(port)); - else - *(volatile unsigned short *)PORT2ADDR(port) = w; -} - -void _outl(unsigned long l, unsigned long port) -{ - *(volatile unsigned long *)PORT2ADDR(port) = l; -} - -void _outb_p(unsigned char b, unsigned long port) -{ - _outb(b, port); - delay(); -} - -void _outw_p(unsigned short w, unsigned long port) -{ - _outw(w, port); - delay(); -} - -void _outl_p(unsigned long l, unsigned long port) -{ - _outl(l, port); - delay(); -} - -void _insb(unsigned int port, void *addr, unsigned long count) -{ - if (port >= LAN_IOSTART && port < LAN_IOEND) - _ne_insb(PORT2ADDR_NE(port), addr, count); - else { - unsigned char *buf = addr; - unsigned char *portp = PORT2ADDR(port); - while (count--) - *buf++ = *(volatile unsigned char *)portp; - } -} - -void _insw(unsigned int port, void *addr, unsigned long count) -{ - unsigned short *buf = addr; - unsigned short *portp; - - if (port >= LAN_IOSTART && port < LAN_IOEND) { - /* - * This portion is only used by smc91111.c to read data - * from the DATA_REG. Do not swap the data. - */ - portp = PORT2ADDR_NE(port); - while (count--) - *buf++ = *(volatile unsigned short *)portp; -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) - } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short), - count, 1); -#endif -#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) - } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { - portp = __port2addr_ata(port); - while (count--) - *buf++ = *(volatile unsigned short *)portp; -#endif - } else { - portp = PORT2ADDR(port); - while (count--) - *buf++ = *(volatile unsigned short *)portp; - } -} - -void _insl(unsigned int port, void *addr, unsigned long count) -{ - unsigned long *buf = addr; - unsigned long *portp; - - portp = PORT2ADDR(port); - while (count--) - *buf++ = *(volatile unsigned long *)portp; -} - -void _outsb(unsigned int port, const void *addr, unsigned long count) -{ - const unsigned char *buf = addr; - unsigned char *portp; - - if (port >= LAN_IOSTART && port < LAN_IOEND) { - portp = PORT2ADDR_NE(port); - while (count--) - _ne_outb(*buf++, portp); - } else { - portp = PORT2ADDR(port); - while (count--) - *(volatile unsigned char *)portp = *buf++; - } -} - -void _outsw(unsigned int port, const void *addr, unsigned long count) -{ - const unsigned short *buf = addr; - unsigned short *portp; - - if (port >= LAN_IOSTART && port < LAN_IOEND) { - /* - * This portion is only used by smc91111.c to write data - * into the DATA_REG. Do not swap the data. - */ - portp = PORT2ADDR_NE(port); - while (count--) - *(volatile unsigned short *)portp = *buf++; -#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) - } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) { - portp = __port2addr_ata(port); - while (count--) - *(volatile unsigned short *)portp = *buf++; -#endif -#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC) - } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) { - pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short), - count, 1); -#endif - } else { - portp = PORT2ADDR(port); - while (count--) - *(volatile unsigned short *)portp = *buf++; - } -} - -void _outsl(unsigned int port, const void *addr, unsigned long count) -{ - const unsigned long *buf = addr; - unsigned char *portp; - - portp = PORT2ADDR(port); - while (count--) - *(volatile unsigned long *)portp = *buf++; -} diff --git a/trunk/arch/m32r/kernel/io_m32700ut.c b/trunk/arch/m32r/kernel/io_m32700ut.c index 939932d6cc00..eda9f963c1eb 100644 --- a/trunk/arch/m32r/kernel/io_m32700ut.c +++ b/trunk/arch/m32r/kernel/io_m32700ut.c @@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port | NONCACHE_OFFSET); + return (void *)(port + NONCACHE_OFFSET); } #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) @@ -45,15 +45,15 @@ static inline void *__port2addr_ata(unsigned long port) static int dummy_reg; switch (port) { - case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET); - case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET); - case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET); - case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET); - case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET); - case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET); - case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET); - case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET); - case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET); + case 0x1f0: return (void *)0xac002000; + case 0x1f1: return (void *)0xac012800; + case 0x1f2: return (void *)0xac012002; + case 0x1f3: return (void *)0xac012802; + case 0x1f4: return (void *)0xac012004; + case 0x1f5: return (void *)0xac012804; + case 0x1f6: return (void *)0xac012006; + case 0x1f7: return (void *)0xac012806; + case 0x3f6: return (void *)0xac01200e; default: return (void *)&dummy_reg; } } @@ -64,8 +64,8 @@ static inline void *__port2addr_ata(unsigned long port) * from 0x10000000 to 0x13ffffff on physical address. * The base address of LAN controller(LAN91C111) is 0x300. */ -#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) -#define LAN_IOEND (0x320 | NONCACHE_OFFSET) +#define LAN_IOSTART 0xa0000300 +#define LAN_IOEND 0xa0000320 static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + 0x10000000); diff --git a/trunk/arch/m32r/kernel/io_mappi.c b/trunk/arch/m32r/kernel/io_mappi.c index a662b537c5ba..3c3da042fbd1 100644 --- a/trunk/arch/m32r/kernel/io_mappi.c +++ b/trunk/arch/m32r/kernel/io_mappi.c @@ -31,7 +31,7 @@ extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port | NONCACHE_OFFSET); + return (void *)(port | (NONCACHE_OFFSET)); } static inline void *_port2addr_ne(unsigned long port) diff --git a/trunk/arch/m32r/kernel/io_mappi2.c b/trunk/arch/m32r/kernel/io_mappi2.c index e72d725606af..df3c729cb3e0 100644 --- a/trunk/arch/m32r/kernel/io_mappi2.c +++ b/trunk/arch/m32r/kernel/io_mappi2.c @@ -33,7 +33,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port | NONCACHE_OFFSET); + return (void *)(port | (NONCACHE_OFFSET)); } #if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC) @@ -42,22 +42,22 @@ static inline void *__port2addr_ata(unsigned long port) static int dummy_reg; switch (port) { - case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET); - case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET); - case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET); - case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET); - case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET); - case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET); - case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET); - case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET); - case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET); + case 0x1f0: return (void *)0xac002000; + case 0x1f1: return (void *)0xac012800; + case 0x1f2: return (void *)0xac012002; + case 0x1f3: return (void *)0xac012802; + case 0x1f4: return (void *)0xac012004; + case 0x1f5: return (void *)0xac012804; + case 0x1f6: return (void *)0xac012006; + case 0x1f7: return (void *)0xac012806; + case 0x3f6: return (void *)0xac01200e; default: return (void *)&dummy_reg; } } #endif -#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) -#define LAN_IOEND (0x320 | NONCACHE_OFFSET) +#define LAN_IOSTART 0xa0000300 +#define LAN_IOEND 0xa0000320 #ifdef CONFIG_CHIP_OPSP static inline void *_port2addr_ne(unsigned long port) { diff --git a/trunk/arch/m32r/kernel/io_mappi3.c b/trunk/arch/m32r/kernel/io_mappi3.c index ed6da930bc64..f80321a58764 100644 --- a/trunk/arch/m32r/kernel/io_mappi3.c +++ b/trunk/arch/m32r/kernel/io_mappi3.c @@ -33,7 +33,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port | NONCACHE_OFFSET); + return (void *)(port + NONCACHE_OFFSET); } #if defined(CONFIG_IDE) @@ -43,42 +43,33 @@ static inline void *__port2addr_ata(unsigned long port) switch (port) { /* IDE0 CF */ - case 0x1f0: return (void *)(0x14002000 | NONCACHE_OFFSET); - case 0x1f1: return (void *)(0x14012800 | NONCACHE_OFFSET); - case 0x1f2: return (void *)(0x14012002 | NONCACHE_OFFSET); - case 0x1f3: return (void *)(0x14012802 | NONCACHE_OFFSET); - case 0x1f4: return (void *)(0x14012004 | NONCACHE_OFFSET); - case 0x1f5: return (void *)(0x14012804 | NONCACHE_OFFSET); - case 0x1f6: return (void *)(0x14012006 | NONCACHE_OFFSET); - case 0x1f7: return (void *)(0x14012806 | NONCACHE_OFFSET); - case 0x3f6: return (void *)(0x1401200e | NONCACHE_OFFSET); + case 0x1f0: return (void *)0xb4002000; + case 0x1f1: return (void *)0xb4012800; + case 0x1f2: return (void *)0xb4012002; + case 0x1f3: return (void *)0xb4012802; + case 0x1f4: return (void *)0xb4012004; + case 0x1f5: return (void *)0xb4012804; + case 0x1f6: return (void *)0xb4012006; + case 0x1f7: return (void *)0xb4012806; + case 0x3f6: return (void *)0xb401200e; /* IDE1 IDE */ - case 0x170: /* Data 16bit */ - return (void *)(0x14810000 | NONCACHE_OFFSET); - case 0x171: /* Features / Error */ - return (void *)(0x14810002 | NONCACHE_OFFSET); - case 0x172: /* Sector count */ - return (void *)(0x14810004 | NONCACHE_OFFSET); - case 0x173: /* Sector number */ - return (void *)(0x14810006 | NONCACHE_OFFSET); - case 0x174: /* Cylinder low */ - return (void *)(0x14810008 | NONCACHE_OFFSET); - case 0x175: /* Cylinder high */ - return (void *)(0x1481000a | NONCACHE_OFFSET); - case 0x176: /* Device head */ - return (void *)(0x1481000c | NONCACHE_OFFSET); - case 0x177: /* Command */ - return (void *)(0x1481000e | NONCACHE_OFFSET); - case 0x376: /* Device control / Alt status */ - return (void *)(0x1480800c | NONCACHE_OFFSET); + case 0x170: return (void *)0xb4810000; /* Data 16bit */ + case 0x171: return (void *)0xb4810002; /* Features / Error */ + case 0x172: return (void *)0xb4810004; /* Sector count */ + case 0x173: return (void *)0xb4810006; /* Sector number */ + case 0x174: return (void *)0xb4810008; /* Cylinder low */ + case 0x175: return (void *)0xb481000a; /* Cylinder high */ + case 0x176: return (void *)0xb481000c; /* Device head */ + case 0x177: return (void *)0xb481000e; /* Command */ + case 0x376: return (void *)0xb480800c; /* Device control / Alt status */ default: return (void *)&dummy_reg; } } #endif -#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) -#define LAN_IOEND (0x320 | NONCACHE_OFFSET) +#define LAN_IOSTART 0xa0000300 +#define LAN_IOEND 0xa0000320 static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + 0x10000000); diff --git a/trunk/arch/m32r/kernel/io_oaks32r.c b/trunk/arch/m32r/kernel/io_oaks32r.c index 910dd131c227..8be323931e4a 100644 --- a/trunk/arch/m32r/kernel/io_oaks32r.c +++ b/trunk/arch/m32r/kernel/io_oaks32r.c @@ -16,7 +16,7 @@ static inline void *_port2addr(unsigned long port) { - return (void *)(port | NONCACHE_OFFSET); + return (void *)(port | (NONCACHE_OFFSET)); } static inline void *_port2addr_ne(unsigned long port) diff --git a/trunk/arch/m32r/kernel/io_opsput.c b/trunk/arch/m32r/kernel/io_opsput.c index bec69297db3c..4793bd18e115 100644 --- a/trunk/arch/m32r/kernel/io_opsput.c +++ b/trunk/arch/m32r/kernel/io_opsput.c @@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int); static inline void *_port2addr(unsigned long port) { - return (void *)(port | NONCACHE_OFFSET); + return (void *)(port | (NONCACHE_OFFSET)); } /* @@ -44,8 +44,8 @@ static inline void *_port2addr(unsigned long port) * from 0x10000000 to 0x13ffffff on physical address. * The base address of LAN controller(LAN91C111) is 0x300. */ -#define LAN_IOSTART (0x300 | NONCACHE_OFFSET) -#define LAN_IOEND (0x320 | NONCACHE_OFFSET) +#define LAN_IOSTART 0xa0000300 +#define LAN_IOEND 0xa0000320 static inline void *_port2addr_ne(unsigned long port) { return (void *)(port + 0x10000000); diff --git a/trunk/arch/m32r/kernel/setup.c b/trunk/arch/m32r/kernel/setup.c index c2e4dccf0112..f722ec8eb021 100644 --- a/trunk/arch/m32r/kernel/setup.c +++ b/trunk/arch/m32r/kernel/setup.c @@ -320,9 +320,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) #elif defined(CONFIG_CHIP_MP) seq_printf(m, "cpu family\t: M32R-MP\n" "cache size\t: I-xxKB/D-xxKB\n"); -#elif defined(CONFIG_CHIP_M32104) - seq_printf(m,"cpu family\t: M32104\n" - "cache size\t: I-8KB/D-8KB\n"); #else seq_printf(m, "cpu family\t: Unknown\n"); #endif @@ -343,8 +340,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "Machine\t\t: uServer\n"); #elif defined(CONFIG_PLAT_OAKS32R) seq_printf(m, "Machine\t\t: OAKS32R\n"); -#elif defined(CONFIG_PLAT_M32104UT) - seq_printf(m, "Machine\t\t: M3T-M32104UT uT Engine board\n"); #else seq_printf(m, "Machine\t\t: Unknown\n"); #endif @@ -394,7 +389,7 @@ unsigned long cpu_initialized __initdata = 0; */ #if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \ - || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) + || defined(CONFIG_CHIP_OPSP) void __init cpu_init (void) { int cpu_id = smp_processor_id(); diff --git a/trunk/arch/m32r/kernel/setup_m32104ut.c b/trunk/arch/m32r/kernel/setup_m32104ut.c deleted file mode 100644 index 6328e1357a80..000000000000 --- a/trunk/arch/m32r/kernel/setup_m32104ut.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * linux/arch/m32r/kernel/setup_m32104ut.c - * - * Setup routines for M32104UT Board - * - * Copyright (c) 2002-2005 Hiroyuki Kondo, Hirokazu Takata, - * Hitoshi Yamamoto, Mamoru Sakugawa, - * Naoto Sugai, Hayato Fujiwara - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) - -icu_data_t icu_data[NR_IRQS]; - -static void disable_m32104ut_irq(unsigned int irq) -{ - unsigned long port, data; - - port = irq2port(irq); - data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7; - outl(data, port); -} - -static void enable_m32104ut_irq(unsigned int irq) -{ - unsigned long port, data; - - port = irq2port(irq); - data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6; - outl(data, port); -} - -static void mask_and_ack_m32104ut(unsigned int irq) -{ - disable_m32104ut_irq(irq); -} - -static void end_m32104ut_irq(unsigned int irq) -{ - enable_m32104ut_irq(irq); -} - -static unsigned int startup_m32104ut_irq(unsigned int irq) -{ - enable_m32104ut_irq(irq); - return (0); -} - -static void shutdown_m32104ut_irq(unsigned int irq) -{ - unsigned long port; - - port = irq2port(irq); - outl(M32R_ICUCR_ILEVEL7, port); -} - -static struct hw_interrupt_type m32104ut_irq_type = -{ - .typename = "M32104UT-IRQ", - .startup = startup_m32104ut_irq, - .shutdown = shutdown_m32104ut_irq, - .enable = enable_m32104ut_irq, - .disable = disable_m32104ut_irq, - .ack = mask_and_ack_m32104ut, - .end = end_m32104ut_irq -}; - -void __init init_IRQ(void) -{ - static int once = 0; - - if (once) - return; - else - once++; - -#if defined(CONFIG_SMC91X) - /* INT#0: LAN controller on M32104UT-LAN (SMC91C111)*/ - irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED; - irq_desc[M32R_IRQ_INT0].handler = &m32104ut_irq_type; - irq_desc[M32R_IRQ_INT0].action = 0; - irq_desc[M32R_IRQ_INT0].depth = 1; - icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD11; /* "H" level sense */ - disable_m32104ut_irq(M32R_IRQ_INT0); -#endif /* CONFIG_SMC91X */ - - /* MFT2 : system timer */ - irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED; - irq_desc[M32R_IRQ_MFT2].handler = &m32104ut_irq_type; - irq_desc[M32R_IRQ_MFT2].action = 0; - irq_desc[M32R_IRQ_MFT2].depth = 1; - icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN; - disable_m32104ut_irq(M32R_IRQ_MFT2); - -#ifdef CONFIG_SERIAL_M32R_SIO - /* SIO0_R : uart receive data */ - irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED; - irq_desc[M32R_IRQ_SIO0_R].handler = &m32104ut_irq_type; - irq_desc[M32R_IRQ_SIO0_R].action = 0; - irq_desc[M32R_IRQ_SIO0_R].depth = 1; - icu_data[M32R_IRQ_SIO0_R].icucr = M32R_ICUCR_IEN; - disable_m32104ut_irq(M32R_IRQ_SIO0_R); - - /* SIO0_S : uart send data */ - irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED; - irq_desc[M32R_IRQ_SIO0_S].handler = &m32104ut_irq_type; - irq_desc[M32R_IRQ_SIO0_S].action = 0; - irq_desc[M32R_IRQ_SIO0_S].depth = 1; - icu_data[M32R_IRQ_SIO0_S].icucr = M32R_ICUCR_IEN; - disable_m32104ut_irq(M32R_IRQ_SIO0_S); -#endif /* CONFIG_SERIAL_M32R_SIO */ -} - -#if defined(CONFIG_SMC91X) - -#define LAN_IOSTART 0x300 -#define LAN_IOEND 0x320 -static struct resource smc91x_resources[] = { - [0] = { - .start = (LAN_IOSTART), - .end = (LAN_IOEND), - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = M32R_IRQ_INT0, - .end = M32R_IRQ_INT0, - .flags = IORESOURCE_IRQ, - } -}; - -static struct platform_device smc91x_device = { - .name = "smc91x", - .id = 0, - .num_resources = ARRAY_SIZE(smc91x_resources), - .resource = smc91x_resources, -}; -#endif - -static int __init platform_init(void) -{ -#if defined(CONFIG_SMC91X) - platform_device_register(&smc91x_device); -#endif - return 0; -} -arch_initcall(platform_init); diff --git a/trunk/arch/m32r/kernel/setup_m32700ut.c b/trunk/arch/m32r/kernel/setup_m32700ut.c index fad1fc99bb27..cb76916b014d 100644 --- a/trunk/arch/m32r/kernel/setup_m32700ut.c +++ b/trunk/arch/m32r/kernel/setup_m32700ut.c @@ -26,7 +26,15 @@ */ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) +#ifndef CONFIG_SMP +typedef struct { + unsigned long icucr; /* ICU Control Register */ +} icu_data_t; +static icu_data_t icu_data[M32700UT_NUM_CPU_IRQ]; +#else icu_data_t icu_data[M32700UT_NUM_CPU_IRQ]; +#endif /* CONFIG_SMP */ + static void disable_m32700ut_irq(unsigned int irq) { diff --git a/trunk/arch/m32r/kernel/setup_mappi.c b/trunk/arch/m32r/kernel/setup_mappi.c index 00f253209cb3..501d798cf050 100644 --- a/trunk/arch/m32r/kernel/setup_mappi.c +++ b/trunk/arch/m32r/kernel/setup_mappi.c @@ -19,6 +19,12 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) +#ifndef CONFIG_SMP +typedef struct { + unsigned long icucr; /* ICU Control Register */ +} icu_data_t; +#endif /* CONFIG_SMP */ + icu_data_t icu_data[NR_IRQS]; static void disable_mappi_irq(unsigned int irq) diff --git a/trunk/arch/m32r/kernel/setup_mappi2.c b/trunk/arch/m32r/kernel/setup_mappi2.c index eebc9d8b4e72..7f2db5bfd626 100644 --- a/trunk/arch/m32r/kernel/setup_mappi2.c +++ b/trunk/arch/m32r/kernel/setup_mappi2.c @@ -19,6 +19,12 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) +#ifndef CONFIG_SMP +typedef struct { + unsigned long icucr; /* ICU Control Register */ +} icu_data_t; +#endif /* CONFIG_SMP */ + icu_data_t icu_data[NR_IRQS]; static void disable_mappi2_irq(unsigned int irq) diff --git a/trunk/arch/m32r/kernel/setup_mappi3.c b/trunk/arch/m32r/kernel/setup_mappi3.c index d2ff021e2d3d..f6ecdf7f555c 100644 --- a/trunk/arch/m32r/kernel/setup_mappi3.c +++ b/trunk/arch/m32r/kernel/setup_mappi3.c @@ -19,6 +19,12 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) +#ifndef CONFIG_SMP +typedef struct { + unsigned long icucr; /* ICU Control Register */ +} icu_data_t; +#endif /* CONFIG_SMP */ + icu_data_t icu_data[NR_IRQS]; static void disable_mappi3_irq(unsigned int irq) diff --git a/trunk/arch/m32r/kernel/setup_oaks32r.c b/trunk/arch/m32r/kernel/setup_oaks32r.c index 0e9e63538c0f..45add5b76f19 100644 --- a/trunk/arch/m32r/kernel/setup_oaks32r.c +++ b/trunk/arch/m32r/kernel/setup_oaks32r.c @@ -18,6 +18,12 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) +#ifndef CONFIG_SMP +typedef struct { + unsigned long icucr; /* ICU Control Register */ +} icu_data_t; +#endif /* CONFIG_SMP */ + icu_data_t icu_data[NR_IRQS]; static void disable_oaks32r_irq(unsigned int irq) diff --git a/trunk/arch/m32r/kernel/setup_opsput.c b/trunk/arch/m32r/kernel/setup_opsput.c index 548e8fc7949b..1fbb140854e7 100644 --- a/trunk/arch/m32r/kernel/setup_opsput.c +++ b/trunk/arch/m32r/kernel/setup_opsput.c @@ -27,7 +27,15 @@ */ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) +#ifndef CONFIG_SMP +typedef struct { + unsigned long icucr; /* ICU Control Register */ +} icu_data_t; +static icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ]; +#else icu_data_t icu_data[OPSPUT_NUM_CPU_IRQ]; +#endif /* CONFIG_SMP */ + static void disable_opsput_irq(unsigned int irq) { diff --git a/trunk/arch/m32r/kernel/setup_usrv.c b/trunk/arch/m32r/kernel/setup_usrv.c index 64be659a23e7..634741bf9d35 100644 --- a/trunk/arch/m32r/kernel/setup_usrv.c +++ b/trunk/arch/m32r/kernel/setup_usrv.c @@ -18,6 +18,12 @@ #define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) +#if !defined(CONFIG_SMP) +typedef struct { + unsigned long icucr; /* ICU Control Register */ +} icu_data_t; +#endif /* CONFIG_SMP */ + icu_data_t icu_data[M32700UT_NUM_CPU_IRQ]; static void disable_mappi_irq(unsigned int irq) diff --git a/trunk/arch/m32r/kernel/time.c b/trunk/arch/m32r/kernel/time.c index b8e68b542302..2ebce2063fea 100644 --- a/trunk/arch/m32r/kernel/time.c +++ b/trunk/arch/m32r/kernel/time.c @@ -57,7 +57,7 @@ static unsigned long do_gettimeoffset(void) #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ - || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) + || defined(CONFIG_CHIP_OPSP) #ifndef CONFIG_SMP unsigned long count; @@ -268,7 +268,7 @@ void __init time_init(void) #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \ - || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) + || defined(CONFIG_CHIP_OPSP) /* M32102 MFT setup */ setup_irq(M32R_IRQ_MFT2, &irq0); diff --git a/trunk/arch/m32r/m32104ut/defconfig.m32104ut b/trunk/arch/m32r/m32104ut/defconfig.m32104ut deleted file mode 100644 index 454de336803a..000000000000 --- a/trunk/arch/m32r/m32104ut/defconfig.m32104ut +++ /dev/null @@ -1,657 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.14 -# Wed Nov 9 16:04:51 2005 -# -CONFIG_M32R=y -# CONFIG_UID16 is not set -CONFIG_GENERIC_ISA_DMA=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -# CONFIG_POSIX_MQUEUE is not set -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -CONFIG_HOTPLUG=y -# CONFIG_KOBJECT_UEVENT is not set -# CONFIG_IKCONFIG is not set -CONFIG_INITRAMFS_SOURCE="" -CONFIG_EMBEDDED=y -# CONFIG_KALLSYMS is not set -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_BASE_FULL=y -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -CONFIG_TINY_SHMEM=y -CONFIG_BASE_SMALL=0 - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Processor type and features -# -# CONFIG_PLAT_MAPPI is not set -# CONFIG_PLAT_USRV is not set -# CONFIG_PLAT_M32700UT is not set -# CONFIG_PLAT_OPSPUT is not set -# CONFIG_PLAT_OAKS32R is not set -# CONFIG_PLAT_MAPPI2 is not set -# CONFIG_PLAT_MAPPI3 is not set -CONFIG_PLAT_M32104UT=y -# CONFIG_CHIP_M32700 is not set -# CONFIG_CHIP_M32102 is not set -CONFIG_CHIP_M32104=y -# CONFIG_CHIP_VDEC2 is not set -# CONFIG_CHIP_OPSP is not set -CONFIG_ISA_M32R=y -CONFIG_BUS_CLOCK=54000000 -CONFIG_TIMER_DIVIDE=128 -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_MEMORY_START=04000000 -CONFIG_MEMORY_SIZE=01000000 -CONFIG_NOHIGHMEM=y -# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -CONFIG_GENERIC_CALIBRATE_DELAY=y -# CONFIG_PREEMPT is not set -# CONFIG_SMP is not set - -# -# Bus options (PCI, PCMCIA, EISA, MCA, ISA) -# -# CONFIG_ISA is not set - -# -# PCCARD (PCMCIA/CardBus) support -# -CONFIG_PCCARD=y -# CONFIG_PCMCIA_DEBUG is not set -CONFIG_PCMCIA=y -CONFIG_PCMCIA_LOAD_CIS=y -CONFIG_PCMCIA_IOCTL=y - -# -# PC-card bridges -# - -# -# PCI Hotplug Support -# - -# -# Executable file formats -# -CONFIG_BINFMT_FLAT=y -# CONFIG_BINFMT_ZFLAT is not set -# CONFIG_BINFMT_SHARED_FLAT is not set -# CONFIG_BINFMT_MISC is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET 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_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# 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_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_BIC=y -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK 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_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_IEEE80211 is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -# CONFIG_DEBUG_DRIVER is not set - -# -# Connector - unified userspace <-> kernelspace linker -# -# CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=y -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y -# CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_AS is not set -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -# CONFIG_ATA_OVER_ETH is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# - -# -# I2O device support -# - -# -# Network device support -# -CONFIG_NETDEVICES=y -CONFIG_DUMMY=y -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# PHY device support -# -# CONFIG_PHYLIB is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -CONFIG_SMC91X=y -# CONFIG_NE2000 is not set - -# -# Ethernet (1000 Mbit) -# - -# -# Ethernet (10000 Mbit) -# - -# -# Token Ring devices -# - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# PCMCIA network device support -# -# CONFIG_NET_PCMCIA is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# -# CONFIG_INPUT is not set - -# -# Hardware I/O ports -# -# CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_SERIAL_M32R_SIO=y -CONFIG_SERIAL_M32R_SIO_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -CONFIG_SOFT_WATCHDOG=y -# CONFIG_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set - -# -# Ftape, the floppy tape device driver -# - -# -# PCMCIA character devices -# -# CONFIG_SYNCLINK_CS is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Hardware Monitoring support -# -# CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set - -# -# Misc devices -# - -# -# Multimedia Capabilities Port drivers -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -# CONFIG_FB is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB_ARCH_HAS_HCD is not set -# CONFIG_USB_ARCH_HAS_OHCI is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# InfiniBand support -# - -# -# SN Devices -# - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -CONFIG_EXT3_FS_POSIX_ACL=y -# 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_FS_POSIX_ACL=y -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_INOTIFY is not set -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y -CONFIG_FAT_DEFAULT_CODEPAGE=932 -CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -CONFIG_CRAMFS=y -# 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=y -# CONFIG_NFS_V3_ACL is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set -CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_LOCKD_V4=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 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_AFS_FS is not set -# CONFIG_9P_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -CONFIG_NLS_CODEPAGE_437=y -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -CONFIG_NLS_CODEPAGE_932=y -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -CONFIG_NLS_UTF8=y - -# -# Profiling support -# -# CONFIG_PROFILING is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_DEBUG_KERNEL=y -CONFIG_MAGIC_SYSRQ=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_DETECT_SOFTLOCKUP=y -# CONFIG_SCHEDSTATS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_BUGVERBOSE is not set -CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_FS is not set -# CONFIG_FRAME_POINTER is not set -# CONFIG_DEBUG_STACKOVERFLOW is not set -# CONFIG_DEBUG_STACK_USAGE is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Hardware crypto devices -# - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -CONFIG_CRC32=y -CONFIG_LIBCRC32C=y -CONFIG_ZLIB_INFLATE=y diff --git a/trunk/arch/m32r/mm/cache.c b/trunk/arch/m32r/mm/cache.c index 9f54dd937013..31b0789c1992 100644 --- a/trunk/arch/m32r/mm/cache.c +++ b/trunk/arch/m32r/mm/cache.c @@ -1,7 +1,7 @@ /* * linux/arch/m32r/mm/cache.c * - * Copyright (C) 2002-2005 Hirokazu Takata, Hayato Fujiwara + * Copyright (C) 2002 Hirokazu Takata */ #include @@ -9,8 +9,7 @@ #undef MCCR -#if defined(CONFIG_CHIP_XNUX2) || defined(CONFIG_CHIP_M32700) \ - || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_OPSP) +#if defined(CONFIG_CHIP_XNUX2) || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_OPSP) /* Cache Control Register */ #define MCCR ((volatile unsigned long*)0xfffffffc) #define MCCR_CC (1UL << 7) /* Cache mode modify bit */ @@ -27,17 +26,7 @@ #define MCCR ((volatile unsigned char*)0xfffffffe) #define MCCR_IIV (1UL << 0) /* I-cache invalidate */ #define MCCR_ICACHE_INV MCCR_IIV -#elif defined(CONFIG_CHIP_M32104) -#define MCCR ((volatile unsigned short*)0xfffffffe) -#define MCCR_IIV (1UL << 8) /* I-cache invalidate */ -#define MCCR_DIV (1UL << 9) /* D-cache invalidate */ -#define MCCR_DCB (1UL << 10) /* D-cache copy back */ -#define MCCR_ICM (1UL << 0) /* I-cache mode [0:off,1:on] */ -#define MCCR_DCM (1UL << 1) /* D-cache mode [0:off,1:on] */ -#define MCCR_ICACHE_INV MCCR_IIV -#define MCCR_DCACHE_CB MCCR_DCB -#define MCCR_DCACHE_CBINV (MCCR_DIV|MCCR_DCB) -#endif +#endif /* CONFIG_CHIP_XNUX2 || CONFIG_CHIP_M32700 */ #ifndef MCCR #error Unknown cache type. @@ -48,42 +37,29 @@ void _flush_cache_all(void) { #if defined(CONFIG_CHIP_M32102) - unsigned char mccr; *MCCR = MCCR_ICACHE_INV; -#elif defined(CONFIG_CHIP_M32104) - unsigned short mccr; - - /* Copyback and invalidate D-cache */ - /* Invalidate I-cache */ - *MCCR |= (MCCR_ICACHE_INV | MCCR_DCACHE_CBINV); #else unsigned long mccr; /* Copyback and invalidate D-cache */ /* Invalidate I-cache */ *MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CBINV; -#endif while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */ +#endif } /* Copy back D-cache and invalidate I-cache all */ void _flush_cache_copyback_all(void) { #if defined(CONFIG_CHIP_M32102) - unsigned char mccr; *MCCR = MCCR_ICACHE_INV; -#elif defined(CONFIG_CHIP_M32104) - unsigned short mccr; - - /* Copyback and invalidate D-cache */ - /* Invalidate I-cache */ - *MCCR |= (MCCR_ICACHE_INV | MCCR_DCACHE_CB); #else unsigned long mccr; /* Copyback D-cache */ /* Invalidate I-cache */ *MCCR = MCCR_ICACHE_INV | MCCR_DCACHE_CB; -#endif while ((mccr = *MCCR) & MCCR_IIV); /* loop while invalidating... */ + +#endif } diff --git a/trunk/arch/m68knommu/kernel/m68k_ksyms.c b/trunk/arch/m68knommu/kernel/m68k_ksyms.c index b2c62eeb3bab..e93a5ad56496 100644 --- a/trunk/arch/m68knommu/kernel/m68k_ksyms.c +++ b/trunk/arch/m68knommu/kernel/m68k_ksyms.c @@ -38,6 +38,8 @@ EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(ip_fast_csum); +EXPORT_SYMBOL(mach_enable_irq); +EXPORT_SYMBOL(mach_disable_irq); EXPORT_SYMBOL(kernel_thread); /* Networking helper routines. */ diff --git a/trunk/arch/m68knommu/kernel/setup.c b/trunk/arch/m68knommu/kernel/setup.c index 93120b9bfff1..abb80fa2b940 100644 --- a/trunk/arch/m68knommu/kernel/setup.c +++ b/trunk/arch/m68knommu/kernel/setup.c @@ -65,6 +65,8 @@ void (*mach_kbd_leds) (unsigned int) = NULL; /* machine dependent irq functions */ void (*mach_init_IRQ) (void) = NULL; irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; +void (*mach_enable_irq) (unsigned int) = NULL; +void (*mach_disable_irq) (unsigned int) = NULL; int (*mach_get_irq_list) (struct seq_file *, void *) = NULL; void (*mach_process_int) (int irq, struct pt_regs *fp) = NULL; void (*mach_trap_init) (void); diff --git a/trunk/arch/ppc/boot/simple/Makefile b/trunk/arch/ppc/boot/simple/Makefile index 9533f8de238f..f3e9c534aa82 100644 --- a/trunk/arch/ppc/boot/simple/Makefile +++ b/trunk/arch/ppc/boot/simple/Makefile @@ -190,8 +190,6 @@ boot-$(CONFIG_REDWOOD_5) += embed_config.o boot-$(CONFIG_REDWOOD_6) += embed_config.o boot-$(CONFIG_8xx) += embed_config.o boot-$(CONFIG_8260) += embed_config.o -boot-$(CONFIG_EP405) += embed_config.o -boot-$(CONFIG_XILINX_ML300) += embed_config.o boot-$(CONFIG_BSEIP) += iic.o boot-$(CONFIG_MBX) += iic.o pci.o qspan_pci.o boot-$(CONFIG_MV64X60) += misc-mv64x60.o diff --git a/trunk/arch/ppc/kernel/idle.c b/trunk/arch/ppc/kernel/idle.c index 1be3ca5bae40..821a75e45602 100644 --- a/trunk/arch/ppc/kernel/idle.c +++ b/trunk/arch/ppc/kernel/idle.c @@ -37,6 +37,7 @@ void default_idle(void) { void (*powersave)(void); + int cpu = smp_processor_id(); powersave = ppc_md.power_save; @@ -46,8 +47,7 @@ void default_idle(void) #ifdef CONFIG_SMP else { set_thread_flag(TIF_POLLING_NRFLAG); - while (!need_resched() && - !cpu_is_offline(smp_processor_id())) + while (!need_resched() && !cpu_is_offline(cpu)) barrier(); clear_thread_flag(TIF_POLLING_NRFLAG); } diff --git a/trunk/arch/ppc/platforms/4xx/ibm440gx.c b/trunk/arch/ppc/platforms/4xx/ibm440gx.c index d24c09ee7b18..956f45e4ef97 100644 --- a/trunk/arch/ppc/platforms/4xx/ibm440gx.c +++ b/trunk/arch/ppc/platforms/4xx/ibm440gx.c @@ -58,6 +58,7 @@ static struct ocp_func_emac_data ibm440gx_emac2_def = { .wol_irq = 65, /* WOL interrupt number */ .mdio_idx = -1, /* No shared MDIO */ .tah_idx = 0, /* TAH device index */ + .jumbo = 1, /* Jumbo frames supported */ }; static struct ocp_func_emac_data ibm440gx_emac3_def = { @@ -71,6 +72,7 @@ static struct ocp_func_emac_data ibm440gx_emac3_def = { .wol_irq = 67, /* WOL interrupt number */ .mdio_idx = -1, /* No shared MDIO */ .tah_idx = 1, /* TAH device index */ + .jumbo = 1, /* Jumbo frames supported */ }; OCP_SYSFS_EMAC_DATA() diff --git a/trunk/arch/ppc/platforms/4xx/ibm440sp.c b/trunk/arch/ppc/platforms/4xx/ibm440sp.c index 71a0117d3597..feb17e41ef69 100644 --- a/trunk/arch/ppc/platforms/4xx/ibm440sp.c +++ b/trunk/arch/ppc/platforms/4xx/ibm440sp.c @@ -31,6 +31,7 @@ static struct ocp_func_emac_data ibm440sp_emac0_def = { .wol_irq = 61, /* WOL interrupt number */ .mdio_idx = -1, /* No shared MDIO */ .tah_idx = -1, /* No TAH */ + .jumbo = 1, /* Jumbo frames supported */ }; OCP_SYSFS_EMAC_DATA() diff --git a/trunk/arch/ppc/platforms/lite5200.c b/trunk/arch/ppc/platforms/lite5200.c index 7ed52dc340c9..d44cc991179f 100644 --- a/trunk/arch/ppc/platforms/lite5200.c +++ b/trunk/arch/ppc/platforms/lite5200.c @@ -196,10 +196,8 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, mpc52xx_set_bat(); /* No ISA bus by default */ -#ifdef CONFIG_PCI isa_io_base = 0; isa_mem_base = 0; -#endif /* Powersave */ /* This is provided as an example on how to do it. But you diff --git a/trunk/arch/ppc/platforms/mpc5200.c b/trunk/arch/ppc/platforms/mpc5200.c new file mode 100644 index 000000000000..a58db438c162 --- /dev/null +++ b/trunk/arch/ppc/platforms/mpc5200.c @@ -0,0 +1,53 @@ +/* + * arch/ppc/platforms/mpc5200.c + * + * OCP Definitions for the boards based on MPC5200 processor. Contains + * definitions for every common peripherals. (Mostly all but PSCs) + * + * Maintainer : Sylvain Munaut + * + * Copyright 2004 Sylvain Munaut + * + * 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 +#include + + +static struct ocp_fs_i2c_data mpc5200_i2c_def = { + .flags = FS_I2C_CLOCK_5200, +}; + + +/* Here is the core_ocp struct. + * With all the devices common to all board. Even if port multiplexing is + * not setup for them (if the user don't want them, just don't select the + * config option). The potentially conflicting devices (like PSCs) goes in + * board specific file. + */ +struct ocp_def core_ocp[] = { + { + .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_IIC, + .index = 0, + .paddr = MPC52xx_I2C1, + .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C1 - Buggy */ + .pm = OCP_CPM_NA, + .additions = &mpc5200_i2c_def, + }, + { + .vendor = OCP_VENDOR_FREESCALE, + .function = OCP_FUNC_IIC, + .index = 1, + .paddr = MPC52xx_I2C2, + .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C2 - Buggy */ + .pm = OCP_CPM_NA, + .additions = &mpc5200_i2c_def, + }, + { /* Terminating entry */ + .vendor = OCP_VENDOR_INVALID + } +}; diff --git a/trunk/arch/ppc/syslib/mpc52xx_pci.c b/trunk/arch/ppc/syslib/mpc52xx_pci.c index 313c96ec7eb1..4ac19080eb85 100644 --- a/trunk/arch/ppc/syslib/mpc52xx_pci.c +++ b/trunk/arch/ppc/syslib/mpc52xx_pci.c @@ -24,12 +24,6 @@ #include -/* This macro is defined to activate the workaround for the bug - 435 of the MPC5200 (L25R). With it activated, we don't do any - 32 bits configuration access during type-1 cycles */ -#define MPC5200_BUG_435_WORKAROUND - - static int mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) @@ -46,39 +40,17 @@ mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, ((bus->number - hose->bus_offset) << 16) | (devfn << 8) | (offset & 0xfc)); - mb(); - -#ifdef MPC5200_BUG_435_WORKAROUND - if (bus->number != hose->bus_offset) { - switch (len) { - case 1: - value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3)); - break; - case 2: - value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1)); - break; - - default: - value = in_le16((u16 __iomem *)hose->cfg_data) | - (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16); - break; - } - } - else -#endif - { - value = in_le32(hose->cfg_data); - if (len != 4) { - value >>= ((offset & 0x3) << 3); - value &= 0xffffffff >> (32 - (len << 3)); - } + value = in_le32(hose->cfg_data); + + if (len != 4) { + value >>= ((offset & 0x3) << 3); + value &= 0xffffffff >> (32 - (len << 3)); } *val = value; out_be32(hose->cfg_addr, 0); - mb(); return PCIBIOS_SUCCESSFUL; } @@ -99,48 +71,21 @@ mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, ((bus->number - hose->bus_offset) << 16) | (devfn << 8) | (offset & 0xfc)); - mb(); - -#ifdef MPC5200_BUG_435_WORKAROUND - if (bus->number != hose->bus_offset) { - switch (len) { - case 1: - out_8(((u8 __iomem *)hose->cfg_data) + - (offset & 3), val); - break; - case 2: - out_le16(((u16 __iomem *)hose->cfg_data) + - ((offset>>1) & 1), val); - break; - - default: - out_le16((u16 __iomem *)hose->cfg_data, - (u16)val); - out_le16(((u16 __iomem *)hose->cfg_data) + 1, - (u16)(val>>16)); - break; - } - } - else -#endif - { - if (len != 4) { - value = in_le32(hose->cfg_data); - offset = (offset & 0x3) << 3; - mask = (0xffffffff >> (32 - (len << 3))); - mask <<= offset; + if (len != 4) { + value = in_le32(hose->cfg_data); - value &= ~mask; - val = value | ((val << offset) & mask); - } + offset = (offset & 0x3) << 3; + mask = (0xffffffff >> (32 - (len << 3))); + mask <<= offset; - out_le32(hose->cfg_data, val); + value &= ~mask; + val = value | ((val << offset) & mask); } - mb(); + + out_le32(hose->cfg_data, val); out_be32(hose->cfg_addr, 0); - mb(); return PCIBIOS_SUCCESSFUL; } @@ -154,12 +99,9 @@ static struct pci_ops mpc52xx_pci_ops = { static void __init mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs) { - u32 tmp; /* Setup control regs */ - tmp = in_be32(&pci_regs->scr); - tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; - out_be32(&pci_regs->scr, tmp); + /* Nothing to do afaik */ /* Setup windows */ out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION( @@ -200,15 +142,16 @@ mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs) /* Not necessary and can be a bad thing if for example the bootloader is displaying a splash screen or ... Just left here for documentation purpose if anyone need it */ - tmp = in_be32(&pci_regs->gscr); #if 0 + u32 tmp; + tmp = in_be32(&pci_regs->gscr); out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR); udelay(50); + out_be32(&pci_regs->gscr, tmp); #endif - out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR); } -static void +static void __init mpc52xx_pci_fixup_resources(struct pci_dev *dev) { int i; diff --git a/trunk/arch/ppc/syslib/mpc52xx_setup.c b/trunk/arch/ppc/syslib/mpc52xx_setup.c index a4a4b02227df..bb2374585a7b 100644 --- a/trunk/arch/ppc/syslib/mpc52xx_setup.c +++ b/trunk/arch/ppc/syslib/mpc52xx_setup.c @@ -84,11 +84,9 @@ mpc52xx_set_bat(void) void __init mpc52xx_map_io(void) { - /* Here we map the MBAR and the whole upper zone. MBAR is only - 64k but we can't map only 64k with BATs. Map the whole - 0xf0000000 range is ok and helps eventual lpb devices placed there */ + /* Here we only map the MBAR */ io_block_mapping( - MPC52xx_MBAR_VIRT, MPC52xx_MBAR, 0x10000000, _PAGE_IO); + MPC52xx_MBAR_VIRT, MPC52xx_MBAR, MPC52xx_MBAR_SIZE, _PAGE_IO); } diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index 6fe532d82417..477ac2758bd5 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -23,14 +23,14 @@ config GENERIC_BUST_SPINLOCK mainmenu "Linux Kernel Configuration" -config S390 +config ARCH_S390 bool default y config UID16 bool default y - depends on !64BIT + depends on ARCH_S390X = 'n' source "init/Kconfig" @@ -38,12 +38,20 @@ menu "Base setup" comment "Processor type and features" -config 64BIT +config ARCH_S390X bool "64 bit kernel" help Select this option if you have a 64 bit IBM zSeries machine and want to use the 64 bit addressing mode. +config 64BIT + def_bool ARCH_S390X + +config ARCH_S390_31 + bool + depends on ARCH_S390X = 'n' + default y + config SMP bool "Symmetric multi-processing support" ---help--- @@ -93,15 +101,20 @@ config MATHEMU on older S/390 machines. Say Y unless you know your machine doesn't need this. -config COMPAT +config S390_SUPPORT bool "Kernel support for 31 bit emulation" - depends on 64BIT + depends on ARCH_S390X help Select this option if you want to enable your system kernel to handle system-calls from ELF binaries for 31 bit ESA. This option (and some other stuff like libraries and such) is needed for executing 31 bit applications. It is safe to say "Y". +config COMPAT + bool + depends on S390_SUPPORT + default y + config SYSVIPC_COMPAT bool depends on COMPAT && SYSVIPC @@ -109,7 +122,7 @@ config SYSVIPC_COMPAT config BINFMT_ELF32 tristate "Kernel support for 31 bit ELF binaries" - depends on COMPAT + depends on S390_SUPPORT help This allows you to run 32-bit Linux/ELF binaries on your zSeries in 64 bit mode. Everybody wants this; say Y. @@ -122,7 +135,7 @@ choice config MARCH_G5 bool "S/390 model G5 and G6" - depends on !64BIT + depends on ARCH_S390_31 help Select this to build a 31 bit kernel that works on all S/390 and zSeries machines. @@ -227,8 +240,8 @@ config MACHCHK_WARNING config QDIO tristate "QDIO support" ---help--- - This driver provides the Queued Direct I/O base support for - IBM mainframes. + This driver provides the Queued Direct I/O base support for the + IBM S/390 (G5 and G6) and eServer zSeries (z800, z890, z900 and z990). For details please refer to the documentation provided by IBM at @@ -250,8 +263,7 @@ config QDIO_DEBUG bool "Extended debugging information" depends on QDIO help - Say Y here to get extended debugging output in - /sys/kernel/debug/s390dbf/qdio... + Say Y here to get extended debugging output in /proc/s390dbf/qdio... Warning: this option reduces the performance of the QDIO module. If unsure, say N. diff --git a/trunk/arch/s390/Makefile b/trunk/arch/s390/Makefile index 6c6b197898d0..73a09a6ee6c8 100644 --- a/trunk/arch/s390/Makefile +++ b/trunk/arch/s390/Makefile @@ -13,14 +13,16 @@ # Copyright (C) 1994 by Linus Torvalds # -ifndef CONFIG_64BIT +ifdef CONFIG_ARCH_S390_31 LDFLAGS := -m elf_s390 CFLAGS += -m31 AFLAGS += -m31 UTS_MACHINE := s390 STACK_SIZE := 8192 CHECKFLAGS += -D__s390__ -else +endif + +ifdef CONFIG_ARCH_S390X LDFLAGS := -m elf64_s390 MODFLAGS += -fpic -D__PIC__ CFLAGS += -m64 diff --git a/trunk/arch/s390/appldata/appldata_base.c b/trunk/arch/s390/appldata/appldata_base.c index d06a8d71c71d..dee6ab54984d 100644 --- a/trunk/arch/s390/appldata/appldata_base.c +++ b/trunk/arch/s390/appldata/appldata_base.c @@ -40,7 +40,7 @@ #define TOD_MICRO 0x01000 /* nr. of TOD clock units for 1 microsecond */ -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X #define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */ #define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */ @@ -54,13 +54,13 @@ #define APPLDATA_GEN_EVENT_RECORD 0x82 #define APPLDATA_START_CONFIG_REC 0x83 -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ /* * Parameter list for DIAGNOSE X'DC' */ -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X struct appldata_parameter_list { u16 diag; /* The DIAGNOSE code X'00DC' */ u8 function; /* The function code for the DIAGNOSE */ @@ -82,7 +82,7 @@ struct appldata_parameter_list { u64 product_id_addr; u64 buffer_addr; }; -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ /* * /proc entries (sysctl) diff --git a/trunk/arch/s390/appldata/appldata_os.c b/trunk/arch/s390/appldata/appldata_os.c index 99ddd3bf2fba..e0a476bf4fd6 100644 --- a/trunk/arch/s390/appldata/appldata_os.c +++ b/trunk/arch/s390/appldata/appldata_os.c @@ -141,19 +141,19 @@ static void appldata_get_os_data(void *data) j = 0; for_each_online_cpu(i) { os_data->os_cpu[j].per_cpu_user = - cputime_to_jiffies(kstat_cpu(i).cpustat.user); + kstat_cpu(i).cpustat.user; os_data->os_cpu[j].per_cpu_nice = - cputime_to_jiffies(kstat_cpu(i).cpustat.nice); + kstat_cpu(i).cpustat.nice; os_data->os_cpu[j].per_cpu_system = - cputime_to_jiffies(kstat_cpu(i).cpustat.system); + kstat_cpu(i).cpustat.system; os_data->os_cpu[j].per_cpu_idle = - cputime_to_jiffies(kstat_cpu(i).cpustat.idle); + kstat_cpu(i).cpustat.idle; os_data->os_cpu[j].per_cpu_irq = - cputime_to_jiffies(kstat_cpu(i).cpustat.irq); + kstat_cpu(i).cpustat.irq; os_data->os_cpu[j].per_cpu_softirq = - cputime_to_jiffies(kstat_cpu(i).cpustat.softirq); + kstat_cpu(i).cpustat.softirq; os_data->os_cpu[j].per_cpu_iowait = - cputime_to_jiffies(kstat_cpu(i).cpustat.iowait); + kstat_cpu(i).cpustat.iowait; j++; } diff --git a/trunk/arch/s390/crypto/Makefile b/trunk/arch/s390/crypto/Makefile index bfe2541dc5cf..96a05e6b51e0 100644 --- a/trunk/arch/s390/crypto/Makefile +++ b/trunk/arch/s390/crypto/Makefile @@ -2,9 +2,7 @@ # Cryptographic API # -obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o -obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o -obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o -obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o +obj-$(CONFIG_CRYPTO_SHA1_Z990) += sha1_z990.o +obj-$(CONFIG_CRYPTO_DES_Z990) += des_z990.o des_check_key.o -obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o +obj-$(CONFIG_CRYPTO_TEST) += crypt_z990_query.o diff --git a/trunk/arch/s390/crypto/aes_s390.c b/trunk/arch/s390/crypto/aes_s390.c deleted file mode 100644 index 7a1033d8e00f..000000000000 --- a/trunk/arch/s390/crypto/aes_s390.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Cryptographic API. - * - * s390 implementation of the AES Cipher Algorithm. - * - * s390 Version: - * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation - * Author(s): Jan Glauber (jang@de.ibm.com) - * - * Derived from "crypto/aes.c" - * - * 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. - * - */ - -#include -#include -#include -#include "crypt_s390.h" - -#define AES_MIN_KEY_SIZE 16 -#define AES_MAX_KEY_SIZE 32 - -/* data block size for all key lengths */ -#define AES_BLOCK_SIZE 16 - -int has_aes_128 = 0; -int has_aes_192 = 0; -int has_aes_256 = 0; - -struct s390_aes_ctx { - u8 iv[AES_BLOCK_SIZE]; - u8 key[AES_MAX_KEY_SIZE]; - int key_len; -}; - -static int aes_set_key(void *ctx, const u8 *in_key, unsigned int key_len, - u32 *flags) -{ - struct s390_aes_ctx *sctx = ctx; - - switch (key_len) { - case 16: - if (!has_aes_128) - goto fail; - break; - case 24: - if (!has_aes_192) - goto fail; - - break; - case 32: - if (!has_aes_256) - goto fail; - break; - default: - /* invalid key length */ - goto fail; - break; - } - - sctx->key_len = key_len; - memcpy(sctx->key, in_key, key_len); - return 0; -fail: - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; - return -EINVAL; -} - -static void aes_encrypt(void *ctx, u8 *out, const u8 *in) -{ - const struct s390_aes_ctx *sctx = ctx; - - switch (sctx->key_len) { - case 16: - crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); - break; - case 24: - crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); - break; - case 32: - crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); - break; - } -} - -static void aes_decrypt(void *ctx, u8 *out, const u8 *in) -{ - const struct s390_aes_ctx *sctx = ctx; - - switch (sctx->key_len) { - case 16: - crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); - break; - case 24: - crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); - break; - case 32: - crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, - AES_BLOCK_SIZE); - break; - } -} - -static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, - const u8 *in, unsigned int nbytes) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); - - switch (sctx->key_len) { - case 16: - crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes); - break; - case 24: - crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes); - break; - case 32: - crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes); - break; - } - return nbytes & ~(AES_BLOCK_SIZE - 1); -} - -static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, - const u8 *in, unsigned int nbytes) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); - - switch (sctx->key_len) { - case 16: - crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes); - break; - case 24: - crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes); - break; - case 32: - crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes); - break; - } - return nbytes & ~(AES_BLOCK_SIZE - 1); -} - -static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, - const u8 *in, unsigned int nbytes) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); - - memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); - switch (sctx->key_len) { - case 16: - crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes); - break; - case 24: - crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes); - break; - case 32: - crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes); - break; - } - memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE); - - return nbytes & ~(AES_BLOCK_SIZE - 1); -} - -static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, - const u8 *in, unsigned int nbytes) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); - - memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); - switch (sctx->key_len) { - case 16: - crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes); - break; - case 24: - crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes); - break; - case 32: - crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes); - break; - } - return nbytes & ~(AES_BLOCK_SIZE - 1); -} - - -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct s390_aes_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = aes_set_key, - .cia_encrypt = aes_encrypt, - .cia_decrypt = aes_decrypt, - .cia_encrypt_ecb = aes_encrypt_ecb, - .cia_decrypt_ecb = aes_decrypt_ecb, - .cia_encrypt_cbc = aes_encrypt_cbc, - .cia_decrypt_cbc = aes_decrypt_cbc, - } - } -}; - -static int __init aes_init(void) -{ - int ret; - - if (crypt_s390_func_available(KM_AES_128_ENCRYPT)) - has_aes_128 = 1; - if (crypt_s390_func_available(KM_AES_192_ENCRYPT)) - has_aes_192 = 1; - if (crypt_s390_func_available(KM_AES_256_ENCRYPT)) - has_aes_256 = 1; - - if (!has_aes_128 && !has_aes_192 && !has_aes_256) - return -ENOSYS; - - ret = crypto_register_alg(&aes_alg); - if (ret != 0) - printk(KERN_INFO "crypt_s390: aes_s390 couldn't be loaded.\n"); - return ret; -} - -static void __exit aes_fini(void) -{ - crypto_unregister_alg(&aes_alg); -} - -module_init(aes_init); -module_exit(aes_fini); - -MODULE_ALIAS("aes"); - -MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/arch/s390/crypto/crypt_s390_query.c b/trunk/arch/s390/crypto/crypt_s390_query.c deleted file mode 100644 index def02bdc44a4..000000000000 --- a/trunk/arch/s390/crypto/crypt_s390_query.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Cryptographic API. - * - * Support for s390 cryptographic instructions. - * Testing module for querying processor crypto capabilities. - * - * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Thomas Spatzier (tspat@de.ibm.com) - * - * 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. - * - */ -#include -#include -#include -#include -#include "crypt_s390.h" - -static void query_available_functions(void) -{ - printk(KERN_INFO "#####################\n"); - - /* query available KM functions */ - printk(KERN_INFO "KM_QUERY: %d\n", - crypt_s390_func_available(KM_QUERY)); - printk(KERN_INFO "KM_DEA: %d\n", - crypt_s390_func_available(KM_DEA_ENCRYPT)); - printk(KERN_INFO "KM_TDEA_128: %d\n", - crypt_s390_func_available(KM_TDEA_128_ENCRYPT)); - printk(KERN_INFO "KM_TDEA_192: %d\n", - crypt_s390_func_available(KM_TDEA_192_ENCRYPT)); - printk(KERN_INFO "KM_AES_128: %d\n", - crypt_s390_func_available(KM_AES_128_ENCRYPT)); - printk(KERN_INFO "KM_AES_192: %d\n", - crypt_s390_func_available(KM_AES_192_ENCRYPT)); - printk(KERN_INFO "KM_AES_256: %d\n", - crypt_s390_func_available(KM_AES_256_ENCRYPT)); - - /* query available KMC functions */ - printk(KERN_INFO "KMC_QUERY: %d\n", - crypt_s390_func_available(KMC_QUERY)); - printk(KERN_INFO "KMC_DEA: %d\n", - crypt_s390_func_available(KMC_DEA_ENCRYPT)); - printk(KERN_INFO "KMC_TDEA_128: %d\n", - crypt_s390_func_available(KMC_TDEA_128_ENCRYPT)); - printk(KERN_INFO "KMC_TDEA_192: %d\n", - crypt_s390_func_available(KMC_TDEA_192_ENCRYPT)); - printk(KERN_INFO "KMC_AES_128: %d\n", - crypt_s390_func_available(KMC_AES_128_ENCRYPT)); - printk(KERN_INFO "KMC_AES_192: %d\n", - crypt_s390_func_available(KMC_AES_192_ENCRYPT)); - printk(KERN_INFO "KMC_AES_256: %d\n", - crypt_s390_func_available(KMC_AES_256_ENCRYPT)); - - /* query available KIMD fucntions */ - printk(KERN_INFO "KIMD_QUERY: %d\n", - crypt_s390_func_available(KIMD_QUERY)); - printk(KERN_INFO "KIMD_SHA_1: %d\n", - crypt_s390_func_available(KIMD_SHA_1)); - printk(KERN_INFO "KIMD_SHA_256: %d\n", - crypt_s390_func_available(KIMD_SHA_256)); - - /* query available KLMD functions */ - printk(KERN_INFO "KLMD_QUERY: %d\n", - crypt_s390_func_available(KLMD_QUERY)); - printk(KERN_INFO "KLMD_SHA_1: %d\n", - crypt_s390_func_available(KLMD_SHA_1)); - printk(KERN_INFO "KLMD_SHA_256: %d\n", - crypt_s390_func_available(KLMD_SHA_256)); - - /* query available KMAC functions */ - printk(KERN_INFO "KMAC_QUERY: %d\n", - crypt_s390_func_available(KMAC_QUERY)); - printk(KERN_INFO "KMAC_DEA: %d\n", - crypt_s390_func_available(KMAC_DEA)); - printk(KERN_INFO "KMAC_TDEA_128: %d\n", - crypt_s390_func_available(KMAC_TDEA_128)); - printk(KERN_INFO "KMAC_TDEA_192: %d\n", - crypt_s390_func_available(KMAC_TDEA_192)); -} - -static int init(void) -{ - struct crypt_s390_query_status status = { - .high = 0, - .low = 0 - }; - - printk(KERN_INFO "crypt_s390: querying available crypto functions\n"); - crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); - printk(KERN_INFO "KM:\t%016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - status.high = status.low = 0; - crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); - printk(KERN_INFO "KMC:\t%016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - status.high = status.low = 0; - crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); - printk(KERN_INFO "KIMD:\t%016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - status.high = status.low = 0; - crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); - printk(KERN_INFO "KLMD:\t%016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - status.high = status.low = 0; - crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); - printk(KERN_INFO "KMAC:\t%016llx %016llx\n", - (unsigned long long) status.high, - (unsigned long long) status.low); - - query_available_functions(); - return -ECANCELED; -} - -static void __exit cleanup(void) -{ -} - -module_init(init); -module_exit(cleanup); - -MODULE_LICENSE("GPL"); diff --git a/trunk/arch/s390/crypto/crypt_s390.h b/trunk/arch/s390/crypto/crypt_z990.h similarity index 50% rename from trunk/arch/s390/crypto/crypt_s390.h rename to trunk/arch/s390/crypto/crypt_z990.h index d1c259a7fe33..4df660b99e5a 100644 --- a/trunk/arch/s390/crypto/crypt_s390.h +++ b/trunk/arch/s390/crypto/crypt_z990.h @@ -1,7 +1,7 @@ /* * Cryptographic API. * - * Support for s390 cryptographic instructions. + * Support for z990 cryptographic instructions. * * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation * Author(s): Thomas Spatzier (tspat@de.ibm.com) @@ -12,108 +12,84 @@ * any later version. * */ -#ifndef _CRYPTO_ARCH_S390_CRYPT_S390_H -#define _CRYPTO_ARCH_S390_CRYPT_S390_H +#ifndef _CRYPTO_ARCH_S390_CRYPT_Z990_H +#define _CRYPTO_ARCH_S390_CRYPT_Z990_H #include -#define CRYPT_S390_OP_MASK 0xFF00 -#define CRYPT_S390_FUNC_MASK 0x00FF +#define CRYPT_Z990_OP_MASK 0xFF00 +#define CRYPT_Z990_FUNC_MASK 0x00FF -/* s930 cryptographic operations */ -enum crypt_s390_operations { - CRYPT_S390_KM = 0x0100, - CRYPT_S390_KMC = 0x0200, - CRYPT_S390_KIMD = 0x0300, - CRYPT_S390_KLMD = 0x0400, - CRYPT_S390_KMAC = 0x0500 + +/*z990 cryptographic operations*/ +enum crypt_z990_operations { + CRYPT_Z990_KM = 0x0100, + CRYPT_Z990_KMC = 0x0200, + CRYPT_Z990_KIMD = 0x0300, + CRYPT_Z990_KLMD = 0x0400, + CRYPT_Z990_KMAC = 0x0500 }; -/* function codes for KM (CIPHER MESSAGE) instruction - * 0x80 is the decipher modifier bit - */ -enum crypt_s390_km_func { - KM_QUERY = CRYPT_S390_KM | 0x0, - KM_DEA_ENCRYPT = CRYPT_S390_KM | 0x1, - KM_DEA_DECRYPT = CRYPT_S390_KM | 0x1 | 0x80, - KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 0x2, - KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 0x2 | 0x80, - KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 0x3, - KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 0x3 | 0x80, - KM_AES_128_ENCRYPT = CRYPT_S390_KM | 0x12, - KM_AES_128_DECRYPT = CRYPT_S390_KM | 0x12 | 0x80, - KM_AES_192_ENCRYPT = CRYPT_S390_KM | 0x13, - KM_AES_192_DECRYPT = CRYPT_S390_KM | 0x13 | 0x80, - KM_AES_256_ENCRYPT = CRYPT_S390_KM | 0x14, - KM_AES_256_DECRYPT = CRYPT_S390_KM | 0x14 | 0x80, +/*function codes for KM (CIPHER MESSAGE) instruction*/ +enum crypt_z990_km_func { + KM_QUERY = CRYPT_Z990_KM | 0, + KM_DEA_ENCRYPT = CRYPT_Z990_KM | 1, + KM_DEA_DECRYPT = CRYPT_Z990_KM | 1 | 0x80, //modifier bit->decipher + KM_TDEA_128_ENCRYPT = CRYPT_Z990_KM | 2, + KM_TDEA_128_DECRYPT = CRYPT_Z990_KM | 2 | 0x80, + KM_TDEA_192_ENCRYPT = CRYPT_Z990_KM | 3, + KM_TDEA_192_DECRYPT = CRYPT_Z990_KM | 3 | 0x80, }; -/* function codes for KMC (CIPHER MESSAGE WITH CHAINING) - * instruction - */ -enum crypt_s390_kmc_func { - KMC_QUERY = CRYPT_S390_KMC | 0x0, - KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 0x1, - KMC_DEA_DECRYPT = CRYPT_S390_KMC | 0x1 | 0x80, - KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 0x2, - KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 0x2 | 0x80, - KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 0x3, - KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 0x3 | 0x80, - KMC_AES_128_ENCRYPT = CRYPT_S390_KMC | 0x12, - KMC_AES_128_DECRYPT = CRYPT_S390_KMC | 0x12 | 0x80, - KMC_AES_192_ENCRYPT = CRYPT_S390_KMC | 0x13, - KMC_AES_192_DECRYPT = CRYPT_S390_KMC | 0x13 | 0x80, - KMC_AES_256_ENCRYPT = CRYPT_S390_KMC | 0x14, - KMC_AES_256_DECRYPT = CRYPT_S390_KMC | 0x14 | 0x80, +/*function codes for KMC (CIPHER MESSAGE WITH CHAINING) instruction*/ +enum crypt_z990_kmc_func { + KMC_QUERY = CRYPT_Z990_KMC | 0, + KMC_DEA_ENCRYPT = CRYPT_Z990_KMC | 1, + KMC_DEA_DECRYPT = CRYPT_Z990_KMC | 1 | 0x80, //modifier bit->decipher + KMC_TDEA_128_ENCRYPT = CRYPT_Z990_KMC | 2, + KMC_TDEA_128_DECRYPT = CRYPT_Z990_KMC | 2 | 0x80, + KMC_TDEA_192_ENCRYPT = CRYPT_Z990_KMC | 3, + KMC_TDEA_192_DECRYPT = CRYPT_Z990_KMC | 3 | 0x80, }; -/* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) - * instruction - */ -enum crypt_s390_kimd_func { - KIMD_QUERY = CRYPT_S390_KIMD | 0, - KIMD_SHA_1 = CRYPT_S390_KIMD | 1, - KIMD_SHA_256 = CRYPT_S390_KIMD | 2, +/*function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) instruction*/ +enum crypt_z990_kimd_func { + KIMD_QUERY = CRYPT_Z990_KIMD | 0, + KIMD_SHA_1 = CRYPT_Z990_KIMD | 1, }; -/* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) - * instruction - */ -enum crypt_s390_klmd_func { - KLMD_QUERY = CRYPT_S390_KLMD | 0, - KLMD_SHA_1 = CRYPT_S390_KLMD | 1, - KLMD_SHA_256 = CRYPT_S390_KLMD | 2, +/*function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) instruction*/ +enum crypt_z990_klmd_func { + KLMD_QUERY = CRYPT_Z990_KLMD | 0, + KLMD_SHA_1 = CRYPT_Z990_KLMD | 1, }; -/* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) - * instruction - */ -enum crypt_s390_kmac_func { - KMAC_QUERY = CRYPT_S390_KMAC | 0, - KMAC_DEA = CRYPT_S390_KMAC | 1, - KMAC_TDEA_128 = CRYPT_S390_KMAC | 2, - KMAC_TDEA_192 = CRYPT_S390_KMAC | 3 +/*function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) instruction*/ +enum crypt_z990_kmac_func { + KMAC_QUERY = CRYPT_Z990_KMAC | 0, + KMAC_DEA = CRYPT_Z990_KMAC | 1, + KMAC_TDEA_128 = CRYPT_Z990_KMAC | 2, + KMAC_TDEA_192 = CRYPT_Z990_KMAC | 3 }; -/* status word for s390 crypto instructions' QUERY functions */ -struct crypt_s390_query_status { +/*status word for z990 crypto instructions' QUERY functions*/ +struct crypt_z990_query_status { u64 high; u64 low; }; /* - * Standard fixup and ex_table sections for crypt_s390 inline functions. - * label 0: the s390 crypto operation - * label 1: just after 1 to catch illegal operation exception - * (unsupported model) + * Standard fixup and ex_table sections for crypt_z990 inline functions. + * label 0: the z990 crypto operation + * label 1: just after 1 to catch illegal operation exception on non-z990 * label 6: the return point after fixup * label 7: set error value if exception _in_ crypto operation * label 8: set error value if illegal operation exception * [ret] is the variable to receive the error code * [ERR] is the error code value */ -#ifndef CONFIG_64BIT -#define __crypt_s390_fixup \ +#ifndef __s390x__ +#define __crypt_z990_fixup \ ".section .fixup,\"ax\" \n" \ "7: lhi %0,%h[e1] \n" \ " bras 1,9f \n" \ @@ -129,8 +105,8 @@ struct crypt_s390_query_status { " .long 0b,7b \n" \ " .long 1b,8b \n" \ ".previous" -#else /* CONFIG_64BIT */ -#define __crypt_s390_fixup \ +#else /* __s390x__ */ +#define __crypt_z990_fixup \ ".section .fixup,\"ax\" \n" \ "7: lhi %0,%h[e1] \n" \ " jg 6b \n" \ @@ -142,25 +118,25 @@ struct crypt_s390_query_status { " .quad 0b,7b \n" \ " .quad 1b,8b \n" \ ".previous" -#endif /* CONFIG_64BIT */ +#endif /* __s390x__ */ /* - * Standard code for setting the result of s390 crypto instructions. + * Standard code for setting the result of z990 crypto instructions. * %0: the register which will receive the result * [result]: the register containing the result (e.g. second operand length * to compute number of processed bytes]. */ -#ifndef CONFIG_64BIT -#define __crypt_s390_set_result \ +#ifndef __s390x__ +#define __crypt_z990_set_result \ " lr %0,%[result] \n" -#else /* CONFIG_64BIT */ -#define __crypt_s390_set_result \ +#else /* __s390x__ */ +#define __crypt_z990_set_result \ " lgr %0,%[result] \n" #endif /* - * Executes the KM (CIPHER MESSAGE) operation of the CPU. - * @param func: the function code passed to KM; see crypt_s390_km_func + * Executes the KM (CIPHER MESSAGE) operation of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_km_func * @param param: address of parameter block; see POP for details on each func * @param dest: address of destination memory area * @param src: address of source memory area @@ -169,9 +145,9 @@ struct crypt_s390_query_status { * for encryption/decryption funcs */ static inline int -crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len) +crypt_z990_km(long func, void* param, u8* dest, const u8* src, long src_len) { - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; register void* __param asm("1") = param; register u8* __dest asm("4") = dest; register const u8* __src asm("2") = src; @@ -180,26 +156,26 @@ crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len) ret = 0; __asm__ __volatile__ ( - "0: .insn rre,0xB92E0000,%1,%2 \n" /* KM opcode */ - "1: brc 1,0b \n" /* handle partial completion */ - __crypt_s390_set_result + "0: .insn rre,0xB92E0000,%1,%2 \n" //KM opcode + "1: brc 1,0b \n" //handle partial completion + __crypt_z990_set_result "6: \n" - __crypt_s390_fixup + __crypt_z990_fixup : "+d" (ret), "+a" (__dest), "+a" (__src), [result] "+d" (__src_len) : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), "a" (__param) : "cc", "memory" ); - if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ + if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ ret = src_len - ret; } return ret; } /* - * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU. - * @param func: the function code passed to KM; see crypt_s390_kmc_func + * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_kmc_func * @param param: address of parameter block; see POP for details on each func * @param dest: address of destination memory area * @param src: address of source memory area @@ -208,9 +184,9 @@ crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len) * for encryption/decryption funcs */ static inline int -crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len) +crypt_z990_kmc(long func, void* param, u8* dest, const u8* src, long src_len) { - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; register void* __param asm("1") = param; register u8* __dest asm("4") = dest; register const u8* __src asm("2") = src; @@ -219,18 +195,18 @@ crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len) ret = 0; __asm__ __volatile__ ( - "0: .insn rre,0xB92F0000,%1,%2 \n" /* KMC opcode */ - "1: brc 1,0b \n" /* handle partial completion */ - __crypt_s390_set_result + "0: .insn rre,0xB92F0000,%1,%2 \n" //KMC opcode + "1: brc 1,0b \n" //handle partial completion + __crypt_z990_set_result "6: \n" - __crypt_s390_fixup + __crypt_z990_fixup : "+d" (ret), "+a" (__dest), "+a" (__src), [result] "+d" (__src_len) : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), "a" (__param) : "cc", "memory" ); - if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ + if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ ret = src_len - ret; } return ret; @@ -238,8 +214,8 @@ crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len) /* * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation - * of the CPU. - * @param func: the function code passed to KM; see crypt_s390_kimd_func + * of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_kimd_func * @param param: address of parameter block; see POP for details on each func * @param src: address of source memory area * @param src_len: length of src operand in bytes @@ -247,9 +223,9 @@ crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len) * for digest funcs */ static inline int -crypt_s390_kimd(long func, void* param, const u8* src, long src_len) +crypt_z990_kimd(long func, void* param, const u8* src, long src_len) { - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; register void* __param asm("1") = param; register const u8* __src asm("2") = src; register long __src_len asm("3") = src_len; @@ -257,25 +233,25 @@ crypt_s390_kimd(long func, void* param, const u8* src, long src_len) ret = 0; __asm__ __volatile__ ( - "0: .insn rre,0xB93E0000,%1,%1 \n" /* KIMD opcode */ - "1: brc 1,0b \n" /* handle partical completion */ - __crypt_s390_set_result + "0: .insn rre,0xB93E0000,%1,%1 \n" //KIMD opcode + "1: brc 1,0b \n" /*handle partical completion of kimd*/ + __crypt_z990_set_result "6: \n" - __crypt_s390_fixup + __crypt_z990_fixup : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), "a" (__param) : "cc", "memory" ); - if (ret >= 0 && (func & CRYPT_S390_FUNC_MASK)){ + if (ret >= 0 && (func & CRYPT_Z990_FUNC_MASK)){ ret = src_len - ret; } return ret; } /* - * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU. - * @param func: the function code passed to KM; see crypt_s390_klmd_func + * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_klmd_func * @param param: address of parameter block; see POP for details on each func * @param src: address of source memory area * @param src_len: length of src operand in bytes @@ -283,9 +259,9 @@ crypt_s390_kimd(long func, void* param, const u8* src, long src_len) * for digest funcs */ static inline int -crypt_s390_klmd(long func, void* param, const u8* src, long src_len) +crypt_z990_klmd(long func, void* param, const u8* src, long src_len) { - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; register void* __param asm("1") = param; register const u8* __src asm("2") = src; register long __src_len asm("3") = src_len; @@ -293,17 +269,17 @@ crypt_s390_klmd(long func, void* param, const u8* src, long src_len) ret = 0; __asm__ __volatile__ ( - "0: .insn rre,0xB93F0000,%1,%1 \n" /* KLMD opcode */ - "1: brc 1,0b \n" /* handle partical completion */ - __crypt_s390_set_result + "0: .insn rre,0xB93F0000,%1,%1 \n" //KLMD opcode + "1: brc 1,0b \n" /*handle partical completion of klmd*/ + __crypt_z990_set_result "6: \n" - __crypt_s390_fixup + __crypt_z990_fixup : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), "a" (__param) : "cc", "memory" ); - if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ + if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ ret = src_len - ret; } return ret; @@ -311,8 +287,8 @@ crypt_s390_klmd(long func, void* param, const u8* src, long src_len) /* * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation - * of the CPU. - * @param func: the function code passed to KM; see crypt_s390_klmd_func + * of the z990 CPU. + * @param func: the function code passed to KM; see crypt_z990_klmd_func * @param param: address of parameter block; see POP for details on each func * @param src: address of source memory area * @param src_len: length of src operand in bytes @@ -320,9 +296,9 @@ crypt_s390_klmd(long func, void* param, const u8* src, long src_len) * for digest funcs */ static inline int -crypt_s390_kmac(long func, void* param, const u8* src, long src_len) +crypt_z990_kmac(long func, void* param, const u8* src, long src_len) { - register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; + register long __func asm("0") = func & CRYPT_Z990_FUNC_MASK; register void* __param asm("1") = param; register const u8* __src asm("2") = src; register long __src_len asm("3") = src_len; @@ -330,58 +306,58 @@ crypt_s390_kmac(long func, void* param, const u8* src, long src_len) ret = 0; __asm__ __volatile__ ( - "0: .insn rre,0xB91E0000,%5,%5 \n" /* KMAC opcode */ - "1: brc 1,0b \n" /* handle partical completion */ - __crypt_s390_set_result + "0: .insn rre,0xB91E0000,%5,%5 \n" //KMAC opcode + "1: brc 1,0b \n" /*handle partical completion of klmd*/ + __crypt_z990_set_result "6: \n" - __crypt_s390_fixup + __crypt_z990_fixup : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), "a" (__param) : "cc", "memory" ); - if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ + if (ret >= 0 && func & CRYPT_Z990_FUNC_MASK){ ret = src_len - ret; } return ret; } /** - * Tests if a specific crypto function is implemented on the machine. + * Tests if a specific z990 crypto function is implemented on the machine. * @param func: the function code of the specific function; 0 if op in general * @return 1 if func available; 0 if func or op in general not available */ static inline int -crypt_s390_func_available(int func) +crypt_z990_func_available(int func) { int ret; - struct crypt_s390_query_status status = { + struct crypt_z990_query_status status = { .high = 0, .low = 0 }; - switch (func & CRYPT_S390_OP_MASK){ - case CRYPT_S390_KM: - ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); + switch (func & CRYPT_Z990_OP_MASK){ + case CRYPT_Z990_KM: + ret = crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0); break; - case CRYPT_S390_KMC: - ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); + case CRYPT_Z990_KMC: + ret = crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0); break; - case CRYPT_S390_KIMD: - ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); + case CRYPT_Z990_KIMD: + ret = crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0); break; - case CRYPT_S390_KLMD: - ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); + case CRYPT_Z990_KLMD: + ret = crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0); break; - case CRYPT_S390_KMAC: - ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); + case CRYPT_Z990_KMAC: + ret = crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0); break; default: ret = 0; return ret; } if (ret >= 0){ - func &= CRYPT_S390_FUNC_MASK; + func &= CRYPT_Z990_FUNC_MASK; func &= 0x7f; //mask modifier bit if (func < 64){ ret = (status.high >> (64 - func - 1)) & 0x1; @@ -394,4 +370,5 @@ crypt_s390_func_available(int func) return ret; } -#endif // _CRYPTO_ARCH_S390_CRYPT_S390_H + +#endif // _CRYPTO_ARCH_S390_CRYPT_Z990_H diff --git a/trunk/arch/s390/crypto/crypt_z990_query.c b/trunk/arch/s390/crypto/crypt_z990_query.c new file mode 100644 index 000000000000..7133983d1384 --- /dev/null +++ b/trunk/arch/s390/crypto/crypt_z990_query.c @@ -0,0 +1,111 @@ +/* + * Cryptographic API. + * + * Support for z990 cryptographic instructions. + * Testing module for querying processor crypto capabilities. + * + * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Thomas Spatzier (tspat@de.ibm.com) + * + * 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. + * + */ +#include +#include +#include +#include +#include "crypt_z990.h" + +static void +query_available_functions(void) +{ + printk(KERN_INFO "#####################\n"); + //query available KM functions + printk(KERN_INFO "KM_QUERY: %d\n", + crypt_z990_func_available(KM_QUERY)); + printk(KERN_INFO "KM_DEA: %d\n", + crypt_z990_func_available(KM_DEA_ENCRYPT)); + printk(KERN_INFO "KM_TDEA_128: %d\n", + crypt_z990_func_available(KM_TDEA_128_ENCRYPT)); + printk(KERN_INFO "KM_TDEA_192: %d\n", + crypt_z990_func_available(KM_TDEA_192_ENCRYPT)); + //query available KMC functions + printk(KERN_INFO "KMC_QUERY: %d\n", + crypt_z990_func_available(KMC_QUERY)); + printk(KERN_INFO "KMC_DEA: %d\n", + crypt_z990_func_available(KMC_DEA_ENCRYPT)); + printk(KERN_INFO "KMC_TDEA_128: %d\n", + crypt_z990_func_available(KMC_TDEA_128_ENCRYPT)); + printk(KERN_INFO "KMC_TDEA_192: %d\n", + crypt_z990_func_available(KMC_TDEA_192_ENCRYPT)); + //query available KIMD fucntions + printk(KERN_INFO "KIMD_QUERY: %d\n", + crypt_z990_func_available(KIMD_QUERY)); + printk(KERN_INFO "KIMD_SHA_1: %d\n", + crypt_z990_func_available(KIMD_SHA_1)); + //query available KLMD functions + printk(KERN_INFO "KLMD_QUERY: %d\n", + crypt_z990_func_available(KLMD_QUERY)); + printk(KERN_INFO "KLMD_SHA_1: %d\n", + crypt_z990_func_available(KLMD_SHA_1)); + //query available KMAC functions + printk(KERN_INFO "KMAC_QUERY: %d\n", + crypt_z990_func_available(KMAC_QUERY)); + printk(KERN_INFO "KMAC_DEA: %d\n", + crypt_z990_func_available(KMAC_DEA)); + printk(KERN_INFO "KMAC_TDEA_128: %d\n", + crypt_z990_func_available(KMAC_TDEA_128)); + printk(KERN_INFO "KMAC_TDEA_192: %d\n", + crypt_z990_func_available(KMAC_TDEA_192)); +} + +static int +init(void) +{ + struct crypt_z990_query_status status = { + .high = 0, + .low = 0 + }; + + printk(KERN_INFO "crypt_z990: querying available crypto functions\n"); + crypt_z990_km(KM_QUERY, &status, NULL, NULL, 0); + printk(KERN_INFO "KM: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_z990_kmc(KMC_QUERY, &status, NULL, NULL, 0); + printk(KERN_INFO "KMC: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_z990_kimd(KIMD_QUERY, &status, NULL, 0); + printk(KERN_INFO "KIMD: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_z990_klmd(KLMD_QUERY, &status, NULL, 0); + printk(KERN_INFO "KLMD: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + status.high = status.low = 0; + crypt_z990_kmac(KMAC_QUERY, &status, NULL, 0); + printk(KERN_INFO "KMAC: %016llx %016llx\n", + (unsigned long long) status.high, + (unsigned long long) status.low); + + query_available_functions(); + return -1; +} + +static void __exit +cleanup(void) +{ +} + +module_init(init); +module_exit(cleanup); + +MODULE_LICENSE("GPL"); diff --git a/trunk/arch/s390/crypto/des_s390.c b/trunk/arch/s390/crypto/des_z990.c similarity index 81% rename from trunk/arch/s390/crypto/des_s390.c rename to trunk/arch/s390/crypto/des_z990.c index a38bb2a3eef6..813cf37b1177 100644 --- a/trunk/arch/s390/crypto/des_s390.c +++ b/trunk/arch/s390/crypto/des_z990.c @@ -1,7 +1,7 @@ /* * Cryptographic API. * - * s390 implementation of the DES Cipher Algorithm. + * z990 implementation of the DES Cipher Algorithm. * * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Thomas Spatzier (tspat@de.ibm.com) @@ -19,7 +19,7 @@ #include #include #include -#include "crypt_s390.h" +#include "crypt_z990.h" #include "crypto_des.h" #define DES_BLOCK_SIZE 8 @@ -31,17 +31,17 @@ #define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE) #define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE -struct crypt_s390_des_ctx { +struct crypt_z990_des_ctx { u8 iv[DES_BLOCK_SIZE]; u8 key[DES_KEY_SIZE]; }; -struct crypt_s390_des3_128_ctx { +struct crypt_z990_des3_128_ctx { u8 iv[DES_BLOCK_SIZE]; u8 key[DES3_128_KEY_SIZE]; }; -struct crypt_s390_des3_192_ctx { +struct crypt_z990_des3_192_ctx { u8 iv[DES_BLOCK_SIZE]; u8 key[DES3_192_KEY_SIZE]; }; @@ -49,7 +49,7 @@ struct crypt_s390_des3_192_ctx { static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) { - struct crypt_s390_des_ctx *dctx; + struct crypt_z990_des_ctx *dctx; int ret; dctx = ctx; @@ -65,26 +65,26 @@ des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) static void des_encrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des_ctx *dctx; + struct crypt_z990_des_ctx *dctx; dctx = ctx; - crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); + crypt_z990_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); } static void des_decrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des_ctx *dctx; + struct crypt_z990_des_ctx *dctx; dctx = ctx; - crypt_s390_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); + crypt_z990_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); } static struct crypto_alg des_alg = { .cra_name = "des", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), + .cra_ctxsize = sizeof(struct crypt_z990_des_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(des_alg.cra_list), .cra_u = { .cipher = { @@ -111,7 +111,7 @@ static int des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) { int i, ret; - struct crypt_s390_des3_128_ctx *dctx; + struct crypt_z990_des3_128_ctx *dctx; const u8* temp_key = key; dctx = ctx; @@ -132,20 +132,20 @@ des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) static void des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_128_ctx *dctx; + struct crypt_z990_des3_128_ctx *dctx; dctx = ctx; - crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, + crypt_z990_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, DES3_128_BLOCK_SIZE); } static void des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_128_ctx *dctx; + struct crypt_z990_des3_128_ctx *dctx; dctx = ctx; - crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, + crypt_z990_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, DES3_128_BLOCK_SIZE); } @@ -153,7 +153,7 @@ static struct crypto_alg des3_128_alg = { .cra_name = "des3_ede128", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = DES3_128_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx), + .cra_ctxsize = sizeof(struct crypt_z990_des3_128_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), .cra_u = { .cipher = { @@ -181,7 +181,7 @@ static int des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) { int i, ret; - struct crypt_s390_des3_192_ctx *dctx; + struct crypt_z990_des3_192_ctx *dctx; const u8* temp_key; dctx = ctx; @@ -206,20 +206,20 @@ des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) static void des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_192_ctx *dctx; + struct crypt_z990_des3_192_ctx *dctx; dctx = ctx; - crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, + crypt_z990_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, DES3_192_BLOCK_SIZE); } static void des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) { - struct crypt_s390_des3_192_ctx *dctx; + struct crypt_z990_des3_192_ctx *dctx; dctx = ctx; - crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, + crypt_z990_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, DES3_192_BLOCK_SIZE); } @@ -227,7 +227,7 @@ static struct crypto_alg des3_192_alg = { .cra_name = "des3_ede", .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = DES3_192_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), + .cra_ctxsize = sizeof(struct crypt_z990_des3_192_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), .cra_u = { .cipher = { @@ -245,9 +245,9 @@ init(void) { int ret; - if (!crypt_s390_func_available(KM_DEA_ENCRYPT) || - !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) || - !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)){ + if (!crypt_z990_func_available(KM_DEA_ENCRYPT) || + !crypt_z990_func_available(KM_TDEA_128_ENCRYPT) || + !crypt_z990_func_available(KM_TDEA_192_ENCRYPT)){ return -ENOSYS; } @@ -262,7 +262,7 @@ init(void) return -EEXIST; } - printk(KERN_INFO "crypt_s390: des_s390 loaded.\n"); + printk(KERN_INFO "crypt_z990: des_z990 loaded.\n"); return 0; } diff --git a/trunk/arch/s390/crypto/sha1_s390.c b/trunk/arch/s390/crypto/sha1_z990.c similarity index 82% rename from trunk/arch/s390/crypto/sha1_s390.c rename to trunk/arch/s390/crypto/sha1_z990.c index 98c896b86dcd..298174ddf5b1 100644 --- a/trunk/arch/s390/crypto/sha1_s390.c +++ b/trunk/arch/s390/crypto/sha1_z990.c @@ -1,7 +1,7 @@ /* * Cryptographic API. * - * s390 implementation of the SHA1 Secure Hash Algorithm. + * z990 implementation of the SHA1 Secure Hash Algorithm. * * Derived from cryptoapi implementation, adapted for in-place * scatterlist interface. Originally based on the public domain @@ -28,22 +28,22 @@ #include #include #include -#include "crypt_s390.h" +#include "crypt_z990.h" #define SHA1_DIGEST_SIZE 20 #define SHA1_BLOCK_SIZE 64 -struct crypt_s390_sha1_ctx { - u64 count; - u32 state[5]; +struct crypt_z990_sha1_ctx { + u64 count; + u32 state[5]; u32 buf_len; - u8 buffer[2 * SHA1_BLOCK_SIZE]; + u8 buffer[2 * SHA1_BLOCK_SIZE]; }; static void sha1_init(void *ctx) { - static const struct crypt_s390_sha1_ctx initstate = { + static const struct crypt_z990_sha1_ctx initstate = { .state = { 0x67452301, 0xEFCDAB89, @@ -58,7 +58,7 @@ sha1_init(void *ctx) static void sha1_update(void *ctx, const u8 *data, unsigned int len) { - struct crypt_s390_sha1_ctx *sctx; + struct crypt_z990_sha1_ctx *sctx; long imd_len; sctx = ctx; @@ -69,7 +69,7 @@ sha1_update(void *ctx, const u8 *data, unsigned int len) //complete full block and hash memcpy(sctx->buffer + sctx->buf_len, data, SHA1_BLOCK_SIZE - sctx->buf_len); - crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, + crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, SHA1_BLOCK_SIZE); data += SHA1_BLOCK_SIZE - sctx->buf_len; len -= SHA1_BLOCK_SIZE - sctx->buf_len; @@ -79,7 +79,7 @@ sha1_update(void *ctx, const u8 *data, unsigned int len) //rest of data contains full blocks? imd_len = len & ~0x3ful; if (imd_len){ - crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len); + crypt_z990_kimd(KIMD_SHA_1, sctx->state, data, imd_len); data += imd_len; len -= imd_len; } @@ -92,7 +92,7 @@ sha1_update(void *ctx, const u8 *data, unsigned int len) static void -pad_message(struct crypt_s390_sha1_ctx* sctx) +pad_message(struct crypt_z990_sha1_ctx* sctx) { int index; @@ -113,11 +113,11 @@ pad_message(struct crypt_s390_sha1_ctx* sctx) static void sha1_final(void* ctx, u8 *out) { - struct crypt_s390_sha1_ctx *sctx = ctx; + struct crypt_z990_sha1_ctx *sctx = ctx; //must perform manual padding pad_message(sctx); - crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len); + crypt_z990_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len); //copy digest to out memcpy(out, sctx->state, SHA1_DIGEST_SIZE); /* Wipe context */ @@ -128,7 +128,7 @@ static struct crypto_alg alg = { .cra_name = "sha1", .cra_flags = CRYPTO_ALG_TYPE_DIGEST, .cra_blocksize = SHA1_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx), + .cra_ctxsize = sizeof(struct crypt_z990_sha1_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), .cra_u = { .digest = { @@ -143,10 +143,10 @@ init(void) { int ret = -ENOSYS; - if (crypt_s390_func_available(KIMD_SHA_1)){ + if (crypt_z990_func_available(KIMD_SHA_1)){ ret = crypto_register_alg(&alg); if (ret == 0){ - printk(KERN_INFO "crypt_s390: sha1_s390 loaded.\n"); + printk(KERN_INFO "crypt_z990: sha1_z990 loaded.\n"); } } return ret; diff --git a/trunk/arch/s390/crypto/sha256_s390.c b/trunk/arch/s390/crypto/sha256_s390.c deleted file mode 100644 index b75bdbd476c7..000000000000 --- a/trunk/arch/s390/crypto/sha256_s390.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Cryptographic API. - * - * s390 implementation of the SHA256 Secure Hash Algorithm. - * - * s390 Version: - * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation - * Author(s): Jan Glauber (jang@de.ibm.com) - * - * Derived from "crypto/sha256.c" - * and "arch/s390/crypto/sha1_s390.c" - * - * 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. - * - */ -#include -#include -#include - -#include "crypt_s390.h" - -#define SHA256_DIGEST_SIZE 32 -#define SHA256_BLOCK_SIZE 64 - -struct s390_sha256_ctx { - u64 count; - u32 state[8]; - u8 buf[2 * SHA256_BLOCK_SIZE]; -}; - -static void sha256_init(void *ctx) -{ - struct s390_sha256_ctx *sctx = ctx; - - sctx->state[0] = 0x6a09e667; - sctx->state[1] = 0xbb67ae85; - sctx->state[2] = 0x3c6ef372; - sctx->state[3] = 0xa54ff53a; - sctx->state[4] = 0x510e527f; - sctx->state[5] = 0x9b05688c; - sctx->state[6] = 0x1f83d9ab; - sctx->state[7] = 0x5be0cd19; - sctx->count = 0; - memset(sctx->buf, 0, sizeof(sctx->buf)); -} - -static void sha256_update(void *ctx, const u8 *data, unsigned int len) -{ - struct s390_sha256_ctx *sctx = ctx; - unsigned int index; - - /* how much is already in the buffer? */ - index = sctx->count / 8 & 0x3f; - - /* update message bit length */ - sctx->count += len * 8; - - /* process one block */ - if ((index + len) >= SHA256_BLOCK_SIZE) { - memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index); - crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, - SHA256_BLOCK_SIZE); - data += SHA256_BLOCK_SIZE - index; - len -= SHA256_BLOCK_SIZE - index; - } - - /* anything left? */ - if (len) - memcpy(sctx->buf + index , data, len); -} - -static void pad_message(struct s390_sha256_ctx* sctx) -{ - int index, end; - - index = sctx->count / 8 & 0x3f; - end = index < 56 ? SHA256_BLOCK_SIZE : 2 * SHA256_BLOCK_SIZE; - - /* start pad with 1 */ - sctx->buf[index] = 0x80; - - /* pad with zeros */ - index++; - memset(sctx->buf + index, 0x00, end - index - 8); - - /* append message length */ - memcpy(sctx->buf + end - 8, &sctx->count, sizeof sctx->count); - - sctx->count = end * 8; -} - -/* Add padding and return the message digest */ -static void sha256_final(void* ctx, u8 *out) -{ - struct s390_sha256_ctx *sctx = ctx; - - /* must perform manual padding */ - pad_message(sctx); - - crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, - sctx->count / 8); - - /* copy digest to out */ - memcpy(out, sctx->state, SHA256_DIGEST_SIZE); - - /* wipe context */ - memset(sctx, 0, sizeof *sctx); -} - -static struct crypto_alg alg = { - .cra_name = "sha256", - .cra_flags = CRYPTO_ALG_TYPE_DIGEST, - .cra_blocksize = SHA256_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct s390_sha256_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(alg.cra_list), - .cra_u = { .digest = { - .dia_digestsize = SHA256_DIGEST_SIZE, - .dia_init = sha256_init, - .dia_update = sha256_update, - .dia_final = sha256_final } } -}; - -static int init(void) -{ - int ret; - - if (!crypt_s390_func_available(KIMD_SHA_256)) - return -ENOSYS; - - ret = crypto_register_alg(&alg); - if (ret != 0) - printk(KERN_INFO "crypt_s390: sha256_s390 couldn't be loaded."); - return ret; -} - -static void __exit fini(void) -{ - crypto_unregister_alg(&alg); -} - -module_init(init); -module_exit(fini); - -MODULE_ALIAS("sha256"); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm"); diff --git a/trunk/arch/s390/defconfig b/trunk/arch/s390/defconfig index 7d23edc6facb..45d44c6bb39d 100644 --- a/trunk/arch/s390/defconfig +++ b/trunk/arch/s390/defconfig @@ -1,12 +1,12 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-rc2 -# Mon Nov 21 13:51:30 2005 +# Linux kernel version: 2.6.14-rc1 +# Wed Sep 14 16:46:19 2005 # CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_S390=y +CONFIG_ARCH_S390=y CONFIG_UID16=y # @@ -64,24 +64,6 @@ CONFIG_MODVERSIONS=y CONFIG_KMOD=y CONFIG_STOP_MACHINE=y -# -# Block layer -# -# CONFIG_LBD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_DEFAULT_AS=y -# CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" - # # Base setup # @@ -89,7 +71,9 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # # Processor type and features # +# CONFIG_ARCH_S390X is not set # CONFIG_64BIT is not set +CONFIG_ARCH_S390_31=y CONFIG_SMP=y CONFIG_NR_CPUS=32 CONFIG_HOTPLUG_CPU=y @@ -113,7 +97,6 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 # # I/O subsystem configuration @@ -205,18 +188,10 @@ CONFIG_IPV6=y # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# CONFIG_NET_SCHED=y CONFIG_NET_SCH_CLK_JIFFIES=y # CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set # CONFIG_NET_SCH_CLK_CPU is not set - -# -# Queueing/Scheduling -# CONFIG_NET_SCH_CBQ=m # CONFIG_NET_SCH_HTB is not set # CONFIG_NET_SCH_HFSC is not set @@ -229,10 +204,8 @@ CONFIG_NET_SCH_GRED=m CONFIG_NET_SCH_DSMARK=m # CONFIG_NET_SCH_NETEM is not set # CONFIG_NET_SCH_INGRESS is not set - -# -# Classification -# +CONFIG_NET_QOS=y +CONFIG_NET_ESTIMATOR=y CONFIG_NET_CLS=y # CONFIG_NET_CLS_BASIC is not set CONFIG_NET_CLS_TCINDEX=m @@ -241,18 +214,18 @@ CONFIG_NET_CLS_ROUTE=y CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m # CONFIG_CLS_U32_PERF is not set +# CONFIG_NET_CLS_IND is not set CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m # CONFIG_NET_EMATCH is not set # CONFIG_NET_CLS_ACT is not set CONFIG_NET_CLS_POLICE=y -# CONFIG_NET_CLS_IND is not set -CONFIG_NET_ESTIMATOR=y # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETFILTER_NETLINK is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -303,7 +276,6 @@ CONFIG_SCSI_FC_ATTRS=y # # SCSI low-level drivers # -# CONFIG_ISCSI_TCP is not set # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_DEBUG is not set CONFIG_ZFCP=y @@ -320,6 +292,7 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set # @@ -332,8 +305,15 @@ CONFIG_DASD_PROFILE=y CONFIG_DASD_ECKD=y CONFIG_DASD_FBA=y CONFIG_DASD_DIAG=y -CONFIG_DASD_EER=m # CONFIG_DASD_CMB is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_ATA_OVER_ETH is not set # @@ -398,6 +378,7 @@ CONFIG_S390_TAPE_34XX=m # CONFIG_VMLOGRDR is not set # CONFIG_VMCP is not set # CONFIG_MONREADER is not set +# CONFIG_DCSS_SHM is not set # # Cryptographic devices @@ -612,8 +593,6 @@ CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y -# CONFIG_DEBUG_VM is not set -# CONFIG_RCU_TORTURE_TEST is not set # # Security options @@ -630,19 +609,17 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA1_S390 is not set +# CONFIG_CRYPTO_SHA1_Z990 is not set # CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA256_S390 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_DES_S390 is not set +# CONFIG_CRYPTO_DES_Z990 is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_AES_S390 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set diff --git a/trunk/arch/s390/kernel/Makefile b/trunk/arch/s390/kernel/Makefile index 4865e4b49464..7434c32bc631 100644 --- a/trunk/arch/s390/kernel/Makefile +++ b/trunk/arch/s390/kernel/Makefile @@ -8,26 +8,31 @@ obj-y := bitmap.o traps.o time.o process.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o -obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) -obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) - extra-y += head.o init_task.o vmlinux.lds obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \ +obj-$(CONFIG_S390_SUPPORT) += compat_linux.o compat_signal.o \ compat_ioctl.o compat_wrapper.o \ compat_exec_domain.o obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o +obj-$(CONFIG_ARCH_S390_31) += entry.o reipl.o +obj-$(CONFIG_ARCH_S390X) += entry64.o reipl64.o + obj-$(CONFIG_VIRT_TIMER) += vtime.o # Kexec part S390_KEXEC_OBJS := machine_kexec.o crash.o -S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) +ifeq ($(CONFIG_ARCH_S390X),y) +S390_KEXEC_OBJS += relocate_kernel64.o +else +S390_KEXEC_OBJS += relocate_kernel.o +endif obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS) + # # This is just to get the dependencies... # diff --git a/trunk/arch/s390/kernel/compat_linux.c b/trunk/arch/s390/kernel/compat_linux.c index 41b197a3f3a3..ed877d0f27e6 100644 --- a/trunk/arch/s390/kernel/compat_linux.c +++ b/trunk/arch/s390/kernel/compat_linux.c @@ -279,7 +279,7 @@ asmlinkage long sys32_getegid16(void) static inline long get_tv32(struct timeval *o, struct compat_timeval *i) { - return (!access_ok(VERIFY_READ, o, sizeof(*o)) || + return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) || (__get_user(o->tv_sec, &i->tv_sec) || __get_user(o->tv_usec, &i->tv_usec))); } diff --git a/trunk/arch/s390/kernel/compat_signal.c b/trunk/arch/s390/kernel/compat_signal.c index fa2b3bc22f20..4ff6808456ea 100644 --- a/trunk/arch/s390/kernel/compat_signal.c +++ b/trunk/arch/s390/kernel/compat_signal.c @@ -467,6 +467,8 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) if (err) goto badframe; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ set_fs (KERNEL_DS); do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]); set_fs (old_fs); diff --git a/trunk/arch/s390/kernel/cpcmd.c b/trunk/arch/s390/kernel/cpcmd.c index 4ef44e536b2c..d47fecb42cc5 100644 --- a/trunk/arch/s390/kernel/cpcmd.c +++ b/trunk/arch/s390/kernel/cpcmd.c @@ -39,7 +39,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) if (response != NULL && rlen > 0) { memset(response, 0, rlen); -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X asm volatile ( "lra 2,0(%2)\n" "lr 4,%3\n" "o 4,%6\n" @@ -55,7 +55,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) : "a" (cpcmd_buf), "d" (cmdlen), "a" (response), "d" (rlen), "m" (mask) : "cc", "2", "3", "4", "5" ); -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ asm volatile ( "lrag 2,0(%2)\n" "lgr 4,%3\n" "o 4,%6\n" @@ -73,11 +73,11 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) : "a" (cpcmd_buf), "d" (cmdlen), "a" (response), "d" (rlen), "m" (mask) : "cc", "2", "3", "4", "5" ); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ EBCASC(response, rlen); } else { return_len = 0; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X asm volatile ( "lra 2,0(%1)\n" "lr 3,%2\n" "diag 2,3,0x8\n" @@ -85,7 +85,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) : "=d" (return_code) : "a" (cpcmd_buf), "d" (cmdlen) : "2", "3" ); -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ asm volatile ( "lrag 2,0(%1)\n" "lgr 3,%2\n" "sam31\n" @@ -95,7 +95,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) : "=d" (return_code) : "a" (cpcmd_buf), "d" (cmdlen) : "2", "3" ); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ } spin_unlock_irqrestore(&cpcmd_lock, flags); if (response_code != NULL) @@ -105,7 +105,7 @@ int __cpcmd(const char *cmd, char *response, int rlen, int *response_code) EXPORT_SYMBOL(__cpcmd); -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X int cpcmd(const char *cmd, char *response, int rlen, int *response_code) { char *lowbuf; @@ -129,4 +129,4 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code) } EXPORT_SYMBOL(cpcmd); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ diff --git a/trunk/arch/s390/kernel/entry64.S b/trunk/arch/s390/kernel/entry64.S index 369ab4413ec7..4eb71ffcf484 100644 --- a/trunk/arch/s390/kernel/entry64.S +++ b/trunk/arch/s390/kernel/entry64.S @@ -213,7 +213,7 @@ sysc_nr_ok: mvc SP_ARGS(8,%r15),SP_R7(%r15) sysc_do_restart: larl %r10,sys_call_table -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ? jno sysc_noemu larl %r10,sys_call_table_emu # use 31 bit emulation system calls @@ -361,7 +361,7 @@ sys_clone_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys_clone # branch to sys_clone -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT sys32_clone_glue: la %r2,SP_PTREGS(%r15) # load pt_regs jg sys32_clone # branch to sys32_clone @@ -383,7 +383,7 @@ sys_execve_glue: bnz 0(%r12) # it did fail -> store result in gpr2 b 6(%r12) # SKIP STG 2,SP_R2(15) in # system_call/sysc_tracesys -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT sys32_execve_glue: la %r2,SP_PTREGS(%r15) # load pt_regs lgr %r12,%r14 # save return address @@ -398,7 +398,7 @@ sys_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_sigreturn # branch to sys_sigreturn -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT sys32_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys32_sigreturn # branch to sys32_sigreturn @@ -408,7 +408,7 @@ sys_rt_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_rt_sigreturn # branch to sys_sigreturn -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT sys32_rt_sigreturn_glue: la %r2,SP_PTREGS(%r15) # load pt_regs as parameter jg sys32_rt_sigreturn # branch to sys32_sigreturn @@ -429,7 +429,7 @@ sys_sigsuspend_glue: la %r14,6(%r14) # skip store of return value jg sys_sigsuspend # branch to sys_sigsuspend -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT sys32_sigsuspend_glue: llgfr %r4,%r4 # unsigned long lgr %r5,%r4 # move mask back @@ -449,7 +449,7 @@ sys_rt_sigsuspend_glue: la %r14,6(%r14) # skip store of return value jg sys_rt_sigsuspend # branch to sys_rt_sigsuspend -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT sys32_rt_sigsuspend_glue: llgfr %r3,%r3 # size_t lgr %r4,%r3 # move sigsetsize parameter @@ -464,7 +464,7 @@ sys_sigaltstack_glue: la %r4,SP_PTREGS(%r15) # load pt_regs as parameter jg sys_sigaltstack # branch to sys_sigreturn -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT sys32_sigaltstack_glue: la %r4,SP_PTREGS(%r15) # load pt_regs as parameter jg sys32_sigaltstack_wrapper # branch to sys_sigreturn @@ -1009,7 +1009,7 @@ sys_call_table: #include "syscalls.S" #undef SYSCALL -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT #define SYSCALL(esa,esame,emu) .long emu .globl sys_call_table_emu diff --git a/trunk/arch/s390/kernel/head.S b/trunk/arch/s390/kernel/head.S index ea88d066bf04..d31a97c89f68 100644 --- a/trunk/arch/s390/kernel/head.S +++ b/trunk/arch/s390/kernel/head.S @@ -30,7 +30,7 @@ #include #include -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X #define ARCH_OFFSET 4 #else #define ARCH_OFFSET 0 @@ -539,7 +539,7 @@ ipl_devno: .word 0 .endm -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X #include "head64.S" #else #include "head31.S" diff --git a/trunk/arch/s390/kernel/machine_kexec.c b/trunk/arch/s390/kernel/machine_kexec.c index f0ed5c642c74..5aa71b05b8ae 100644 --- a/trunk/arch/s390/kernel/machine_kexec.c +++ b/trunk/arch/s390/kernel/machine_kexec.c @@ -85,7 +85,7 @@ kexec_halt_all_cpus(void *kernel_image) pfault_fini(); #endif - if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) + if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid)) signal_processor(smp_processor_id(), sigp_stop); /* Wait for all other cpus to enter stopped state */ diff --git a/trunk/arch/s390/kernel/module.c b/trunk/arch/s390/kernel/module.c index c271cdab58e2..607d506689c8 100644 --- a/trunk/arch/s390/kernel/module.c +++ b/trunk/arch/s390/kernel/module.c @@ -37,11 +37,11 @@ #define DEBUGP(fmt , ...) #endif -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X #define PLT_ENTRY_SIZE 12 -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ #define PLT_ENTRY_SIZE 20 -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ void *module_alloc(unsigned long size) { @@ -294,17 +294,17 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, unsigned int *ip; ip = me->module_core + me->arch.plt_offset + info->plt_offset; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */ ip[1] = 0x100607f1; ip[2] = val; -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ ip[0] = 0x0d10e310; /* basr 1,0; lg 1,10(1); br 1 */ ip[1] = 0x100a0004; ip[2] = 0x07f10000; ip[3] = (unsigned int) (val >> 32); ip[4] = (unsigned int) val; -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ info->plt_initialized = 1; } if (r_type == R_390_PLTOFF16 || diff --git a/trunk/arch/s390/kernel/process.c b/trunk/arch/s390/kernel/process.c index a942bf2d58e9..78b64fe5e7c2 100644 --- a/trunk/arch/s390/kernel/process.c +++ b/trunk/arch/s390/kernel/process.c @@ -235,7 +235,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, /* Save access registers to new thread structure. */ save_access_regs(&p->thread.acrs[0]); -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X /* * save fprs to current->thread.fp_regs to merge them with * the emulated registers and then copy the result to the child. @@ -247,7 +247,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, /* Set a new TLS ? */ if (clone_flags & CLONE_SETTLS) p->thread.acrs[0] = regs->gprs[6]; -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ /* Save the fpu registers to new thread structure. */ save_fp_regs(&p->thread.fp_regs); p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _REGION_TABLE; @@ -260,7 +260,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, p->thread.acrs[1] = (unsigned int) regs->gprs[6]; } } -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ /* start new process with ar4 pointing to the correct address space */ p->thread.mm_segment = get_fs(); /* Don't copy debug registers */ @@ -339,16 +339,16 @@ asmlinkage long sys_execve(struct pt_regs regs) */ int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) { -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X /* * save fprs to current->thread.fp_regs to merge them with * the emulated registers and then copy the result to the dump. */ save_fp_regs(¤t->thread.fp_regs); memcpy(fpregs, ¤t->thread.fp_regs, sizeof(s390_fp_regs)); -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ save_fp_regs(fpregs); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ return 1; } diff --git a/trunk/arch/s390/kernel/ptrace.c b/trunk/arch/s390/kernel/ptrace.c index 8ecda6d66de4..06afa3103ace 100644 --- a/trunk/arch/s390/kernel/ptrace.c +++ b/trunk/arch/s390/kernel/ptrace.c @@ -42,7 +42,7 @@ #include #include -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT #include "compat_ptrace.h" #endif @@ -59,7 +59,7 @@ FixPerRegisters(struct task_struct *task) if (per_info->single_step) { per_info->control_regs.bits.starting_addr = 0; -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT if (test_thread_flag(TIF_31BIT)) per_info->control_regs.bits.ending_addr = 0x7fffffffUL; else @@ -112,7 +112,7 @@ ptrace_disable(struct task_struct *child) clear_single_step(child); } -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X # define __ADDR_MASK 3 #else # define __ADDR_MASK 7 @@ -138,7 +138,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) * an alignment of 4. Programmers from hell... */ mask = __ADDR_MASK; -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X if (addr >= (addr_t) &dummy->regs.acrs && addr < (addr_t) &dummy->regs.orig_gpr2) mask = 3; @@ -160,7 +160,7 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data) * access registers are stored in the thread structure */ offset = addr - (addr_t) &dummy->regs.acrs; -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X /* * Very special case: old & broken 64 bit gdb reading * from acrs[15]. Result is a 64 bit value. Read the @@ -218,7 +218,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) * an alignment of 4. Programmers from hell indeed... */ mask = __ADDR_MASK; -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X if (addr >= (addr_t) &dummy->regs.acrs && addr < (addr_t) &dummy->regs.orig_gpr2) mask = 3; @@ -231,13 +231,13 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) * psw and gprs are stored on the stack */ if (addr == (addr_t) &dummy->regs.psw.mask && -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT data != PSW_MASK_MERGE(PSW_USER32_BITS, data) && #endif data != PSW_MASK_MERGE(PSW_USER_BITS, data)) /* Invalid psw mask. */ return -EINVAL; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X if (addr == (addr_t) &dummy->regs.psw.addr) /* I'd like to reject addresses without the high order bit but older gdb's rely on it */ @@ -250,7 +250,7 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data) * access registers are stored in the thread structure */ offset = addr - (addr_t) &dummy->regs.acrs; -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X /* * Very special case: old & broken 64 bit gdb writing * to acrs[15] with a 64 bit value. Ignore the lower @@ -357,7 +357,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data) return ptrace_request(child, request, addr, data); } -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT /* * Now the fun part starts... a 31 bit program running in the * 31 bit emulation tracing another program. PTRACE_PEEKTEXT, @@ -629,7 +629,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) return peek_user(child, addr, data); if (request == PTRACE_POKEUSR && addr == PT_IEEE_IP) return poke_user(child, addr, data); -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT if (request == PTRACE_PEEKUSR && addr == PT32_IEEE_IP && test_thread_flag(TIF_31BIT)) return peek_user_emu31(child, addr, data); @@ -695,7 +695,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) /* Do requests that differ for 31/64 bit */ default: -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT if (test_thread_flag(TIF_31BIT)) return do_ptrace_emu31(child, request, addr, data); #endif diff --git a/trunk/arch/s390/kernel/reipl_diag.c b/trunk/arch/s390/kernel/reipl_diag.c index 1f33951ba439..83cb42bc0b76 100644 --- a/trunk/arch/s390/kernel/reipl_diag.c +++ b/trunk/arch/s390/kernel/reipl_diag.c @@ -26,7 +26,7 @@ void reipl_diag(void) " st %%r4,%0\n" " st %%r5,%1\n" ".section __ex_table,\"a\"\n" -#ifdef CONFIG_64BIT +#ifdef __s390x__ " .align 8\n" " .quad 0b, 0b\n" #else diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index b03847d100d9..31e7b19348b7 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -427,7 +427,7 @@ setup_lowcore(void) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE; lc->current_task = (unsigned long) init_thread_union.thread_info.task; lc->thread_info = (unsigned long) &init_thread_union; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X if (MACHINE_HAS_IEEE) { lc->extended_save_area_addr = (__u32) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0); @@ -562,21 +562,21 @@ setup_arch(char **cmdline_p) /* * print what head.S has found out about the machine */ -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X printk((MACHINE_IS_VM) ? "We are running under VM (31 bit mode)\n" : "We are running native (31 bit mode)\n"); printk((MACHINE_HAS_IEEE) ? "This machine has an IEEE fpu\n" : "This machine has no IEEE fpu\n"); -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ printk((MACHINE_IS_VM) ? "We are running under VM (64 bit mode)\n" : "We are running native (64 bit mode)\n"); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ ROOT_DEV = Root_RAM0; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X memory_end = memory_size & ~0x400000UL; /* align memory end to 4MB */ /* * We need some free virtual space to be able to do vmalloc. @@ -585,9 +585,9 @@ setup_arch(char **cmdline_p) */ if (memory_end > 1920*1024*1024) memory_end = 1920*1024*1024; -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ memory_end = memory_size & ~0x200000UL; /* detected in head.s */ -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ init_mm.start_code = PAGE_OFFSET; init_mm.end_code = (unsigned long) &_etext; diff --git a/trunk/arch/s390/kernel/signal.c b/trunk/arch/s390/kernel/signal.c index 6ae4a77270b5..6e0110d71191 100644 --- a/trunk/arch/s390/kernel/signal.c +++ b/trunk/arch/s390/kernel/signal.c @@ -254,9 +254,9 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) if (restore_sigregs(regs, &frame->uc.uc_mcontext)) goto badframe; - if (do_sigaltstack(&frame->uc.uc_stack, NULL, - regs->gprs[15]) == -EFAULT) - goto badframe; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]); return regs->gprs[2]; badframe: @@ -501,7 +501,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (signr > 0) { /* Whee! Actually deliver the signal. */ -#ifdef CONFIG_COMPAT +#ifdef CONFIG_S390_SUPPORT if (test_thread_flag(TIF_31BIT)) { extern void handle_signal32(unsigned long sig, struct k_sigaction *ka, diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index e10f4ca00499..5856b3fda6bf 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -263,7 +263,7 @@ static void do_machine_restart(void * __unused) int cpu; static atomic_t cpuid = ATOMIC_INIT(-1); - if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) + if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid)) signal_processor(smp_processor_id(), sigp_stop); /* Wait for all other cpus to enter stopped state */ @@ -313,7 +313,7 @@ static void do_machine_halt(void * __unused) { static atomic_t cpuid = ATOMIC_INIT(-1); - if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) { + if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) { smp_send_stop(); if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0) cpcmd(vmhalt_cmd, NULL, 0, NULL); @@ -332,7 +332,7 @@ static void do_machine_power_off(void * __unused) { static atomic_t cpuid = ATOMIC_INIT(-1); - if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) == -1) { + if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) { smp_send_stop(); if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0) cpcmd(vmpoff_cmd, NULL, 0, NULL); @@ -402,7 +402,7 @@ static void smp_ext_bitcall_others(ec_bit_sig sig) } } -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X /* * this function sends a 'purge tlb' signal to another CPU. */ @@ -416,7 +416,7 @@ void smp_ptlb_all(void) on_each_cpu(smp_ptlb_callback, NULL, 0, 1); } EXPORT_SYMBOL(smp_ptlb_all); -#endif /* ! CONFIG_64BIT */ +#endif /* ! CONFIG_ARCH_S390X */ /* * this function sends a 'reschedule' IPI to another CPU. @@ -783,7 +783,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (stack == 0ULL) panic("smp_boot_cpus failed to allocate memory\n"); lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE); -#ifndef CONFIG_64BIT +#ifndef __s390x__ if (MACHINE_HAS_IEEE) { lowcore_ptr[i]->extended_save_area_addr = (__u32) __get_free_pages(GFP_KERNEL,0); @@ -793,7 +793,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) } #endif } -#ifndef CONFIG_64BIT +#ifndef __s390x__ if (MACHINE_HAS_IEEE) ctl_set_bit(14, 29); /* enable extended save area */ #endif diff --git a/trunk/arch/s390/kernel/sys_s390.c b/trunk/arch/s390/kernel/sys_s390.c index 6a63553493c5..efe6b83b53f7 100644 --- a/trunk/arch/s390/kernel/sys_s390.c +++ b/trunk/arch/s390/kernel/sys_s390.c @@ -26,7 +26,9 @@ #include #include #include +#ifdef CONFIG_ARCH_S390X #include +#endif /* CONFIG_ARCH_S390X */ #include #include @@ -119,7 +121,7 @@ asmlinkage long old_mmap(struct mmap_arg_struct __user *arg) return error; } -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X struct sel_arg_struct { unsigned long n; fd_set *inp, *outp, *exp; @@ -136,7 +138,7 @@ asmlinkage long old_select(struct sel_arg_struct __user *arg) return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp); } -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. @@ -209,7 +211,7 @@ asmlinkage long sys_ipc(uint call, int first, unsigned long second, return -EINVAL; } -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X asmlinkage long s390x_newuname(struct new_utsname __user *name) { int ret = sys_newuname(name); @@ -233,12 +235,12 @@ asmlinkage long s390x_personality(unsigned long personality) return ret; } -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ /* * Wrapper function for sys_fadvise64/fadvise64_64 */ -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X asmlinkage long s390_fadvise64(int fd, u32 offset_high, u32 offset_low, size_t len, int advice) diff --git a/trunk/arch/s390/kernel/traps.c b/trunk/arch/s390/kernel/traps.c index 95d109968619..c5bd36fae56b 100644 --- a/trunk/arch/s390/kernel/traps.c +++ b/trunk/arch/s390/kernel/traps.c @@ -67,13 +67,13 @@ extern pgm_check_handler_t do_monitor_call; #define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; }) -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X #define FOURLONG "%08lx %08lx %08lx %08lx\n" static int kstack_depth_to_print = 12; -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ #define FOURLONG "%016lx %016lx %016lx %016lx\n" static int kstack_depth_to_print = 20; -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ /* * For show_trace we have tree different stack to consider: @@ -702,12 +702,12 @@ void __init trap_init(void) pgm_check_table[0x11] = &do_dat_exception; pgm_check_table[0x12] = &translation_exception; pgm_check_table[0x13] = &special_op_exception; -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X pgm_check_table[0x38] = &do_dat_exception; pgm_check_table[0x39] = &do_dat_exception; pgm_check_table[0x3A] = &do_dat_exception; pgm_check_table[0x3B] = &do_dat_exception; -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ pgm_check_table[0x15] = &operand_exception; pgm_check_table[0x1C] = &space_switch_exception; pgm_check_table[0x1D] = &hfp_sqrt_exception; diff --git a/trunk/arch/s390/kernel/vmlinux.lds.S b/trunk/arch/s390/kernel/vmlinux.lds.S index 9289face3027..89fdb3808bc0 100644 --- a/trunk/arch/s390/kernel/vmlinux.lds.S +++ b/trunk/arch/s390/kernel/vmlinux.lds.S @@ -5,7 +5,7 @@ #include #include -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") OUTPUT_ARCH(s390) ENTRY(_start) diff --git a/trunk/arch/s390/lib/Makefile b/trunk/arch/s390/lib/Makefile index d9b97b3c597f..b701efa1f00e 100644 --- a/trunk/arch/s390/lib/Makefile +++ b/trunk/arch/s390/lib/Makefile @@ -4,5 +4,6 @@ EXTRA_AFLAGS := -traditional -lib-y += delay.o string.o spinlock.o -lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o) +lib-y += delay.o string.o +lib-$(CONFIG_ARCH_S390_31) += uaccess.o spinlock.o +lib-$(CONFIG_ARCH_S390X) += uaccess64.o spinlock.o diff --git a/trunk/arch/s390/lib/spinlock.c b/trunk/arch/s390/lib/spinlock.c index 68d79c502081..2dc14e9c8327 100644 --- a/trunk/arch/s390/lib/spinlock.c +++ b/trunk/arch/s390/lib/spinlock.c @@ -29,7 +29,7 @@ __setup("spin_retry=", spin_retry_setup); static inline void _diag44(void) { -#ifdef CONFIG_64BIT +#ifdef __s390x__ if (MACHINE_HAS_DIAG44) #endif asm volatile("diag 0,0,0x44"); diff --git a/trunk/arch/s390/mm/extmem.c b/trunk/arch/s390/mm/extmem.c index a9566bcab682..506a33b51e4f 100644 --- a/trunk/arch/s390/mm/extmem.c +++ b/trunk/arch/s390/mm/extmem.c @@ -143,7 +143,7 @@ dcss_diag (__u8 func, void *parameter, rx = (unsigned long) parameter; ry = (unsigned long) func; __asm__ __volatile__( -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X " sam31\n" // switch to 31 bit " diag %0,%1,0x64\n" " sam64\n" // switch back to 64 bit diff --git a/trunk/arch/s390/mm/fault.c b/trunk/arch/s390/mm/fault.c index 81ade401b073..fb2607c369ed 100644 --- a/trunk/arch/s390/mm/fault.c +++ b/trunk/arch/s390/mm/fault.c @@ -31,17 +31,17 @@ #include #include -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X #define __FAIL_ADDR_MASK 0x7ffff000 #define __FIXUP_MASK 0x7fffffff #define __SUBCODE_MASK 0x0200 #define __PF_RES_FIELD 0ULL -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ #define __FAIL_ADDR_MASK -4096L #define __FIXUP_MASK ~0L #define __SUBCODE_MASK 0x0600 #define __PF_RES_FIELD 0x8000000000000000ULL -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ #ifdef CONFIG_SYSCTL extern int sysctl_userprocess_debug; @@ -393,11 +393,11 @@ int pfault_init(void) "2:\n" ".section __ex_table,\"a\"\n" " .align 4\n" -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X " .long 0b,1b\n" -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ " .quad 0b,1b\n" -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ ".previous" : "=d" (rc) : "a" (&refbk), "m" (refbk) : "cc" ); __ctl_set_bit(0, 9); @@ -417,11 +417,11 @@ void pfault_fini(void) "0:\n" ".section __ex_table,\"a\"\n" " .align 4\n" -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X " .long 0b,0b\n" -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ " .quad 0b,0b\n" -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ ".previous" : : "a" (&refbk), "m" (refbk) : "cc" ); } diff --git a/trunk/arch/s390/mm/init.c b/trunk/arch/s390/mm/init.c index df953383724d..6ec5cd981e74 100644 --- a/trunk/arch/s390/mm/init.c +++ b/trunk/arch/s390/mm/init.c @@ -44,7 +44,7 @@ void diag10(unsigned long addr) { if (addr >= 0x7ff00000) return; -#ifdef CONFIG_64BIT +#ifdef __s390x__ asm volatile ( " sam31\n" " diag %0,%0,0x10\n" @@ -106,7 +106,7 @@ extern unsigned long __initdata zholes_size[]; * paging_init() sets up the page tables */ -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X void __init paging_init(void) { pgd_t * pg_dir; @@ -175,7 +175,7 @@ void __init paging_init(void) return; } -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ void __init paging_init(void) { pgd_t * pg_dir; @@ -256,7 +256,7 @@ void __init paging_init(void) return; } -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ void __init mem_init(void) { diff --git a/trunk/arch/s390/mm/mmap.c b/trunk/arch/s390/mm/mmap.c index 356257c171de..fb187e5a54b4 100644 --- a/trunk/arch/s390/mm/mmap.c +++ b/trunk/arch/s390/mm/mmap.c @@ -50,7 +50,7 @@ static inline unsigned long mmap_base(void) static inline int mmap_is_legacy(void) { -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X /* * Force standard allocation for 64 bit programs. */ diff --git a/trunk/arch/s390/oprofile/Makefile b/trunk/arch/s390/oprofile/Makefile index 537b2d840e69..ec349276258a 100644 --- a/trunk/arch/s390/oprofile/Makefile +++ b/trunk/arch/s390/oprofile/Makefile @@ -6,4 +6,4 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -oprofile-y := $(DRIVER_OBJS) init.o backtrace.o +oprofile-y := $(DRIVER_OBJS) init.o diff --git a/trunk/arch/s390/oprofile/backtrace.c b/trunk/arch/s390/oprofile/backtrace.c deleted file mode 100644 index bc4b84a35cad..000000000000 --- a/trunk/arch/s390/oprofile/backtrace.c +++ /dev/null @@ -1,79 +0,0 @@ -/** - * arch/s390/oprofile/backtrace.c - * - * S390 Version - * Copyright (C) 2005 IBM Corporation, IBM Deutschland Entwicklung GmbH. - * Author(s): Andreas Krebbel - */ - -#include - -#include /* for struct stack_frame */ - -static unsigned long -__show_trace(unsigned int *depth, unsigned long sp, - unsigned long low, unsigned long high) -{ - struct stack_frame *sf; - struct pt_regs *regs; - - while (*depth) { - sp = sp & PSW_ADDR_INSN; - if (sp < low || sp > high - sizeof(*sf)) - return sp; - sf = (struct stack_frame *) sp; - (*depth)--; - oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN); - - /* Follow the backchain. */ - while (*depth) { - low = sp; - sp = sf->back_chain & PSW_ADDR_INSN; - if (!sp) - break; - if (sp <= low || sp > high - sizeof(*sf)) - return sp; - sf = (struct stack_frame *) sp; - (*depth)--; - oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN); - - } - - if (*depth == 0) - break; - - /* Zero backchain detected, check for interrupt frame. */ - sp = (unsigned long) (sf + 1); - if (sp <= low || sp > high - sizeof(*regs)) - return sp; - regs = (struct pt_regs *) sp; - (*depth)--; - oprofile_add_trace(sf->gprs[8] & PSW_ADDR_INSN); - low = sp; - sp = regs->gprs[15]; - } - return sp; -} - -void s390_backtrace(struct pt_regs * const regs, unsigned int depth) -{ - unsigned long head; - struct stack_frame* head_sf; - - if (user_mode (regs)) - return; - - head = regs->gprs[15]; - head_sf = (struct stack_frame*)head; - - if (!head_sf->back_chain) - return; - - head = head_sf->back_chain; - - head = __show_trace(&depth, head, S390_lowcore.async_stack - ASYNC_SIZE, - S390_lowcore.async_stack); - - __show_trace(&depth, head, S390_lowcore.thread_info, - S390_lowcore.thread_info + THREAD_SIZE); -} diff --git a/trunk/arch/s390/oprofile/init.c b/trunk/arch/s390/oprofile/init.c index 7a995113b918..a65ead0e200a 100644 --- a/trunk/arch/s390/oprofile/init.c +++ b/trunk/arch/s390/oprofile/init.c @@ -12,12 +12,8 @@ #include #include - -extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); - int __init oprofile_arch_init(struct oprofile_operations* ops) { - ops->backtrace = s390_backtrace; return -ENODEV; } diff --git a/trunk/arch/um/drivers/chan_kern.c b/trunk/arch/um/drivers/chan_kern.c index cd13b91b9ff6..5b58fad45290 100644 --- a/trunk/arch/um/drivers/chan_kern.c +++ b/trunk/arch/um/drivers/chan_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -58,7 +58,7 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts) { my_puts("Using a channel type which is configured out of " "UML\n"); - return NULL; + return(NULL); } static int not_configged_open(int input, int output, int primary, void *data, @@ -66,7 +66,7 @@ static int not_configged_open(int input, int output, int primary, void *data, { my_puts("Using a channel type which is configured out of " "UML\n"); - return -ENODEV; + return(-ENODEV); } static void not_configged_close(int fd, void *data) @@ -79,21 +79,21 @@ static int not_configged_read(int fd, char *c_out, void *data) { my_puts("Using a channel type which is configured out of " "UML\n"); - return -EIO; + return(-EIO); } static int not_configged_write(int fd, const char *buf, int len, void *data) { my_puts("Using a channel type which is configured out of " "UML\n"); - return -EIO; + return(-EIO); } static int not_configged_console_write(int fd, const char *buf, int len) { my_puts("Using a channel type which is configured out of " "UML\n"); - return -EIO; + return(-EIO); } static int not_configged_window_size(int fd, void *data, unsigned short *rows, @@ -101,7 +101,7 @@ static int not_configged_window_size(int fd, void *data, unsigned short *rows, { my_puts("Using a channel type which is configured out of " "UML\n"); - return -ENODEV; + return(-ENODEV); } static void not_configged_free(void *data) @@ -135,17 +135,17 @@ int generic_read(int fd, char *c_out, void *unused) n = os_read_file(fd, c_out, sizeof(*c_out)); if(n == -EAGAIN) - return 0; + return(0); else if(n == 0) - return -EIO; - return n; + return(-EIO); + return(n); } /* XXX Trivial wrapper around os_write_file */ int generic_write(int fd, const char *buf, int n, void *unused) { - return os_write_file(fd, buf, n); + return(os_write_file(fd, buf, n)); } int generic_window_size(int fd, void *unused, unsigned short *rows_out, @@ -156,14 +156,14 @@ int generic_window_size(int fd, void *unused, unsigned short *rows_out, ret = os_window_size(fd, &rows, &cols); if(ret < 0) - return ret; + return(ret); ret = ((*rows_out != rows) || (*cols_out != cols)); *rows_out = rows; *cols_out = cols; - return ret; + return(ret); } void generic_free(void *data) @@ -186,29 +186,25 @@ static void tty_receive_char(struct tty_struct *tty, char ch) } } - if((tty->flip.flag_buf_ptr == NULL) || + if((tty->flip.flag_buf_ptr == NULL) || (tty->flip.char_buf_ptr == NULL)) return; tty_insert_flip_char(tty, ch, TTY_NORMAL); } -static int open_one_chan(struct chan *chan) +static int open_one_chan(struct chan *chan, int input, int output, int primary) { int fd; - if(chan->opened) - return 0; - - if(chan->ops->open == NULL) - fd = 0; - else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary, - chan->data, &chan->dev); - if(fd < 0) - return fd; + if(chan->opened) return(0); + if(chan->ops->open == NULL) fd = 0; + else fd = (*chan->ops->open)(input, output, primary, chan->data, + &chan->dev); + if(fd < 0) return(fd); chan->fd = fd; chan->opened = 1; - return 0; + return(0); } int open_chan(struct list_head *chans) @@ -219,11 +215,11 @@ int open_chan(struct list_head *chans) list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); - ret = open_one_chan(chan); - if(chan->primary) - err = ret; + ret = open_one_chan(chan, chan->input, chan->output, + chan->primary); + if(chan->primary) err = ret; } - return err; + return(err); } void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) @@ -240,65 +236,20 @@ void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) } } -void enable_chan(struct line *line) +void enable_chan(struct list_head *chans, struct tty_struct *tty) { struct list_head *ele; struct chan *chan; - list_for_each(ele, &line->chan_list){ + list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); - if(open_one_chan(chan)) - continue; - - if(chan->enabled) - continue; - line_setup_irq(chan->fd, chan->input, chan->output, line, - chan); - chan->enabled = 1; - } -} - -static LIST_HEAD(irqs_to_free); - -void free_irqs(void) -{ - struct chan *chan; - - while(!list_empty(&irqs_to_free)){ - chan = list_entry(irqs_to_free.next, struct chan, free_list); - list_del(&chan->free_list); + if(!chan->opened) continue; - if(chan->input) - free_irq(chan->line->driver->read_irq, chan); - if(chan->output) - free_irq(chan->line->driver->write_irq, chan); - chan->enabled = 0; - } -} - -static void close_one_chan(struct chan *chan, int delay_free_irq) -{ - if(!chan->opened) - return; - - if(delay_free_irq){ - list_add(&chan->free_list, &irqs_to_free); + line_setup_irq(chan->fd, chan->input, chan->output, tty); } - else { - if(chan->input) - free_irq(chan->line->driver->read_irq, chan); - if(chan->output) - free_irq(chan->line->driver->write_irq, chan); - chan->enabled = 0; - } - if(chan->ops->close != NULL) - (*chan->ops->close)(chan->fd, chan->data); - - chan->opened = 0; - chan->fd = -1; } -void close_chan(struct list_head *chans, int delay_free_irq) +void close_chan(struct list_head *chans) { struct chan *chan; @@ -308,37 +259,15 @@ void close_chan(struct list_head *chans, int delay_free_irq) * so it must be the last closed. */ list_for_each_entry_reverse(chan, chans, list) { - close_one_chan(chan, delay_free_irq); - } -} - -void deactivate_chan(struct list_head *chans, int irq) -{ - struct list_head *ele; - - struct chan *chan; - list_for_each(ele, chans) { - chan = list_entry(ele, struct chan, list); - - if(chan->enabled && chan->input) - deactivate_fd(chan->fd, irq); - } -} - -void reactivate_chan(struct list_head *chans, int irq) -{ - struct list_head *ele; - struct chan *chan; - - list_for_each(ele, chans) { - chan = list_entry(ele, struct chan, list); - - if(chan->enabled && chan->input) - reactivate_fd(chan->fd, irq); + if(!chan->opened) continue; + if(chan->ops->close != NULL) + (*chan->ops->close)(chan->fd, chan->data); + chan->opened = 0; + chan->fd = -1; } } -int write_chan(struct list_head *chans, const char *buf, int len, +int write_chan(struct list_head *chans, const char *buf, int len, int write_irq) { struct list_head *ele; @@ -356,7 +285,7 @@ int write_chan(struct list_head *chans, const char *buf, int len, reactivate_fd(chan->fd, write_irq); } } - return ret; + return(ret); } int console_write_chan(struct list_head *chans, const char *buf, int len) @@ -372,18 +301,19 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) n = chan->ops->console_write(chan->fd, buf, len); if(chan->primary) ret = n; } - return ret; + return(ret); } -int console_open_chan(struct line *line, struct console *co, - struct chan_opts *opts) +int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts) { - int err; - - err = open_chan(&line->chan_list); - if(err) - return err; + if (!list_empty(&line->chan_list)) + return 0; + if (0 != parse_chan_pair(line->init_str, &line->chan_list, + line->init_pri, co->index, opts)) + return -1; + if (0 != open_chan(&line->chan_list)) + return -1; printk("Console initialized on /dev/%s%d\n",co->name,co->index); return 0; } @@ -397,36 +327,32 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out, list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); if(chan->primary){ - if(chan->ops->window_size == NULL) - return 0; - return chan->ops->window_size(chan->fd, chan->data, - rows_out, cols_out); + if(chan->ops->window_size == NULL) return(0); + return(chan->ops->window_size(chan->fd, chan->data, + rows_out, cols_out)); } } - return 0; + return(0); } -void free_one_chan(struct chan *chan, int delay_free_irq) +void free_one_chan(struct chan *chan) { list_del(&chan->list); - - close_one_chan(chan, delay_free_irq); - if(chan->ops->free != NULL) (*chan->ops->free)(chan->data); - + free_irq_by_fd(chan->fd); if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); kfree(chan); } -void free_chan(struct list_head *chans, int delay_free_irq) +void free_chan(struct list_head *chans) { struct list_head *ele, *next; struct chan *chan; list_for_each_safe(ele, next, chans){ chan = list_entry(ele, struct chan, list); - free_one_chan(chan, delay_free_irq); + free_one_chan(chan); } } @@ -437,23 +363,23 @@ static int one_chan_config_string(struct chan *chan, char *str, int size, if(chan == NULL){ CONFIG_CHUNK(str, size, n, "none", 1); - return n; + return(n); } CONFIG_CHUNK(str, size, n, chan->ops->type, 0); if(chan->dev == NULL){ CONFIG_CHUNK(str, size, n, "", 1); - return n; + return(n); } CONFIG_CHUNK(str, size, n, ":", 0); CONFIG_CHUNK(str, size, n, chan->dev, 0); - return n; + return(n); } -static int chan_pair_config_string(struct chan *in, struct chan *out, +static int chan_pair_config_string(struct chan *in, struct chan *out, char *str, int size, char **error_out) { int n; @@ -464,7 +390,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, if(in == out){ CONFIG_CHUNK(str, size, n, "", 1); - return n; + return(n); } CONFIG_CHUNK(str, size, n, ",", 1); @@ -473,10 +399,10 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, size -= n; CONFIG_CHUNK(str, size, n, "", 1); - return n; + return(n); } -int chan_config_string(struct list_head *chans, char *str, int size, +int chan_config_string(struct list_head *chans, char *str, int size, char **error_out) { struct list_head *ele; @@ -492,7 +418,7 @@ int chan_config_string(struct list_head *chans, char *str, int size, out = chan; } - return chan_pair_config_string(in, out, str, size, error_out); + return(chan_pair_config_string(in, out, str, size, error_out)); } struct chan_type { @@ -536,7 +462,7 @@ struct chan_type chan_table[] = { #endif }; -static struct chan *parse_chan(struct line *line, char *str, int device, +static struct chan *parse_chan(char *str, int pri, int device, struct chan_opts *opts) { struct chan_type *entry; @@ -558,42 +484,36 @@ static struct chan *parse_chan(struct line *line, char *str, int device, if(ops == NULL){ my_printf("parse_chan couldn't parse \"%s\"\n", str); - return NULL; + return(NULL); } - if(ops->init == NULL) - return NULL; + if(ops->init == NULL) return(NULL); data = (*ops->init)(str, device, opts); - if(data == NULL) - return NULL; + if(data == NULL) return(NULL); chan = kmalloc(sizeof(*chan), GFP_ATOMIC); - if(chan == NULL) - return NULL; + if(chan == NULL) return(NULL); *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), - .free_list = - LIST_HEAD_INIT(chan->free_list), - .line = line, .primary = 1, .input = 0, .output = 0, .opened = 0, - .enabled = 0, .fd = -1, + .pri = pri, .ops = ops, .data = data }); - return chan; + return(chan); } -int parse_chan_pair(char *str, struct line *line, int device, +int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, struct chan_opts *opts) { - struct list_head *chans = &line->chan_list; struct chan *new, *chan; char *in, *out; if(!list_empty(chans)){ chan = list_entry(chans->next, struct chan, list); - free_chan(chans, 0); + if(chan->pri >= pri) return(0); + free_chan(chans); INIT_LIST_HEAD(chans); } @@ -602,30 +522,24 @@ int parse_chan_pair(char *str, struct line *line, int device, in = str; *out = '\0'; out++; - new = parse_chan(line, in, device, opts); - if(new == NULL) - return -1; - + new = parse_chan(in, pri, device, opts); + if(new == NULL) return(-1); new->input = 1; list_add(&new->list, chans); - new = parse_chan(line, out, device, opts); - if(new == NULL) - return -1; - + new = parse_chan(out, pri, device, opts); + if(new == NULL) return(-1); list_add(&new->list, chans); new->output = 1; } else { - new = parse_chan(line, str, device, opts); - if(new == NULL) - return -1; - + new = parse_chan(str, pri, device, opts); + if(new == NULL) return(-1); list_add(&new->list, chans); new->input = 1; new->output = 1; } - return 0; + return(0); } int chan_out_fd(struct list_head *chans) @@ -636,9 +550,9 @@ int chan_out_fd(struct list_head *chans) list_for_each(ele, chans){ chan = list_entry(ele, struct chan, list); if(chan->primary && chan->output) - return chan->fd; + return(chan->fd); } - return -1; + return(-1); } void chan_interrupt(struct list_head *chans, struct work_struct *task, @@ -653,9 +567,9 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task, chan = list_entry(ele, struct chan, list); if(!chan->input || (chan->ops->read == NULL)) continue; do { - if((tty != NULL) && + if((tty != NULL) && (tty->flip.count >= TTY_FLIPBUF_SIZE)){ - schedule_delayed_work(task, 1); + schedule_work(task); goto out; } err = chan->ops->read(chan->fd, &c, chan->data); @@ -668,12 +582,29 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task, if(chan->primary){ if(tty != NULL) tty_hangup(tty); - close_chan(chans, 1); + line_disable(tty, irq); + close_chan(chans); + free_chan(chans); return; } - else close_one_chan(chan, 1); + else { + if(chan->ops->close != NULL) + chan->ops->close(chan->fd, chan->data); + free_one_chan(chan); + } } } out: if(tty) tty_flip_buffer_push(tty); } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/drivers/line.c b/trunk/arch/um/drivers/line.c index 46ceb25a9959..e0fdffa2d542 100644 --- a/trunk/arch/um/drivers/line.c +++ b/trunk/arch/um/drivers/line.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -23,9 +23,8 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) { - struct chan *chan = data; - struct line *line = chan->line; - struct tty_struct *tty = line->tty; + struct tty_struct *tty = data; + struct line *line = tty->driver_data; if (line) chan_interrupt(&line->chan_list, &line->task, tty, irq); @@ -34,11 +33,10 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) static void line_timer_cb(void *arg) { - struct line *line = arg; + struct tty_struct *tty = arg; + struct line *line = tty->driver_data; - if(!line->throttled) - chan_interrupt(&line->chan_list, &line->task, line->tty, - line->driver->read_irq); + line_interrupt(line->driver->read_irq, arg, NULL); } /* Returns the free space inside the ring buffer of this line. @@ -126,8 +124,7 @@ static int buffer_data(struct line *line, const char *buf, int len) if (len < end){ memcpy(line->tail, buf, len); line->tail += len; - } - else { + } else { /* The circular buffer is wrapping */ memcpy(line->tail, buf, end); buf += end; @@ -173,7 +170,7 @@ static int flush_buffer(struct line *line) } count = line->tail - line->head; - n = write_chan(&line->chan_list, line->head, count, + n = write_chan(&line->chan_list, line->head, count, line->driver->write_irq); if(n < 0) @@ -230,7 +227,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) if (err <= 0 && (err != -EAGAIN || !ret)) ret = err; } else { - n = write_chan(&line->chan_list, buf, len, + n = write_chan(&line->chan_list, buf, len, line->driver->write_irq); if (n < 0) { ret = n; @@ -341,36 +338,11 @@ int line_ioctl(struct tty_struct *tty, struct file * file, return ret; } -void line_throttle(struct tty_struct *tty) -{ - struct line *line = tty->driver_data; - - deactivate_chan(&line->chan_list, line->driver->read_irq); - line->throttled = 1; -} - -void line_unthrottle(struct tty_struct *tty) -{ - struct line *line = tty->driver_data; - - line->throttled = 0; - chan_interrupt(&line->chan_list, &line->task, tty, - line->driver->read_irq); - - /* Maybe there is enough stuff pending that calling the interrupt - * throttles us again. In this case, line->throttled will be 1 - * again and we shouldn't turn the interrupt back on. - */ - if(!line->throttled) - reactivate_chan(&line->chan_list, line->driver->read_irq); -} - static irqreturn_t line_write_interrupt(int irq, void *data, struct pt_regs *unused) { - struct chan *chan = data; - struct line *line = chan->line; - struct tty_struct *tty = line->tty; + struct tty_struct *tty = data; + struct line *line = tty->driver_data; int err; /* Interrupts are enabled here because we registered the interrupt with @@ -392,7 +364,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data, if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && (tty->ldisc.write_wakeup != NULL)) (tty->ldisc.write_wakeup)(tty); - + /* BLOCKING mode * In blocking mode, everything sleeps on tty->write_wait. * Sleeping in the console driver would break non-blocking @@ -404,29 +376,53 @@ static irqreturn_t line_write_interrupt(int irq, void *data, return IRQ_HANDLED; } -int line_setup_irq(int fd, int input, int output, struct line *line, void *data) +int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) { + struct line *line = tty->driver_data; struct line_driver *driver = line->driver; int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; if (input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, - line_interrupt, flags, - driver->read_irq_name, data); + line_interrupt, flags, + driver->read_irq_name, tty); if (err) return err; if (output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, - line_write_interrupt, flags, - driver->write_irq_name, data); + line_write_interrupt, flags, + driver->write_irq_name, tty); line->have_irq = 1; return err; } -int line_open(struct line *lines, struct tty_struct *tty) +void line_disable(struct tty_struct *tty, int current_irq) +{ + struct line *line = tty->driver_data; + + if(!line->have_irq) + return; + + if(line->driver->read_irq == current_irq) + free_irq_later(line->driver->read_irq, tty); + else { + free_irq(line->driver->read_irq, tty); + } + + if(line->driver->write_irq == current_irq) + free_irq_later(line->driver->write_irq, tty); + else { + free_irq(line->driver->write_irq, tty); + } + + line->have_irq = 0; +} + +int line_open(struct line *lines, struct tty_struct *tty, + struct chan_opts *opts) { struct line *line; - int err = -ENODEV; + int err = 0; line = &lines[tty->index]; tty->driver_data = line; @@ -434,29 +430,31 @@ int line_open(struct line *lines, struct tty_struct *tty) /* The IRQ which takes this lock is not yet enabled and won't be run * before the end, so we don't need to use spin_lock_irq.*/ spin_lock(&line->lock); - - tty->driver_data = line; - line->tty = tty; - if(!line->valid) - goto out; - - if(tty->count == 1){ - /* Here the device is opened, if necessary, and interrupt - * is registered. - */ - enable_chan(line); - INIT_WORK(&line->task, line_timer_cb, line); - - if(!line->sigio){ - chan_enable_winch(&line->chan_list, tty); - line->sigio = 1; + if (tty->count == 1) { + if (!line->valid) { + err = -ENODEV; + goto out; } + if (list_empty(&line->chan_list)) { + err = parse_chan_pair(line->init_str, &line->chan_list, + line->init_pri, tty->index, opts); + if(err) goto out; + err = open_chan(&line->chan_list); + if(err) goto out; + } + /* Here the interrupt is registered.*/ + enable_chan(&line->chan_list, tty); + INIT_WORK(&line->task, line_timer_cb, tty); + } - chan_window_size(&line->chan_list, &tty->winsize.ws_row, - &tty->winsize.ws_col); + if(!line->sigio){ + chan_enable_winch(&line->chan_list, tty); + line->sigio = 1; } + chan_window_size(&line->chan_list, &tty->winsize.ws_row, + &tty->winsize.ws_col); + line->count++; - err = 0; out: spin_unlock(&line->lock); return err; @@ -476,14 +474,15 @@ void line_close(struct tty_struct *tty, struct file * filp) /* We ignore the error anyway! */ flush_buffer(line); - if(tty->count == 1){ - line->tty = NULL; + line->count--; + if (tty->count == 1) { + line_disable(tty, -1); tty->driver_data = NULL; + } - if(line->sigio){ - unregister_winch(tty); - line->sigio = 0; - } + if((line->count == 0) && line->sigio){ + unregister_winch(tty); + line->sigio = 0; } spin_unlock_irq(&line->lock); @@ -494,15 +493,17 @@ void close_lines(struct line *lines, int nlines) int i; for(i = 0; i < nlines; i++) - close_chan(&lines[i].chan_list, 0); + close_chan(&lines[i].chan_list); } /* Common setup code for both startup command line and mconsole initialization. * @lines contains the the array (of size @num) to modify; * @init is the setup string; - */ + * @all_allowed is a boolean saying if we can setup the whole @lines + * at once. For instance, it will be usually true for startup init. (where we + * can use con=xterm) and false for mconsole.*/ -int line_setup(struct line *lines, unsigned int num, char *init) +int line_setup(struct line *lines, unsigned int num, char *init, int all_allowed) { int i, n; char *end; @@ -511,11 +512,10 @@ int line_setup(struct line *lines, unsigned int num, char *init) /* We said con=/ssl= instead of con#=, so we are configuring all * consoles at once.*/ n = -1; - } - else { + } else { n = simple_strtoul(init, &end, 0); if(*end != '='){ - printk(KERN_ERR "line_setup failed to parse \"%s\"\n", + printk(KERN_ERR "line_setup failed to parse \"%s\"\n", init); return 0; } @@ -527,9 +527,8 @@ int line_setup(struct line *lines, unsigned int num, char *init) printk("line_setup - %d out of range ((0 ... %d) allowed)\n", n, num - 1); return 0; - } - else if (n >= 0){ - if (lines[n].tty != NULL) { + } else if (n >= 0){ + if (lines[n].count > 0) { printk("line_setup - device %d is open\n", n); return 0; } @@ -540,10 +539,13 @@ int line_setup(struct line *lines, unsigned int num, char *init) else { lines[n].init_str = init; lines[n].valid = 1; - } + } } - } - else { + } else if(!all_allowed){ + printk("line_setup - can't configure all devices from " + "mconsole\n"); + return 0; + } else { for(i = 0; i < num; i++){ if(lines[i].init_pri <= INIT_ALL){ lines[i].init_pri = INIT_ALL; @@ -555,33 +557,18 @@ int line_setup(struct line *lines, unsigned int num, char *init) } } } - return n == -1 ? num : n; + return 1; } -int line_config(struct line *lines, unsigned int num, char *str, - struct chan_opts *opts) +int line_config(struct line *lines, unsigned int num, char *str) { - struct line *line; - char *new; - int n; + char *new = uml_strdup(str); - if(*str == '='){ - printk("line_config - can't configure all devices from " - "mconsole\n"); - return 1; - } - - new = kstrdup(str, GFP_KERNEL); if(new == NULL){ - printk("line_config - kstrdup failed\n"); - return 1; + printk("line_config - uml_strdup failed\n"); + return -ENOMEM; } - n = line_setup(lines, num, new); - if(n < 0) - return 1; - - line = &lines[n]; - return parse_chan_pair(line->init_str, line, n, opts); + return !line_setup(lines, num, new, 0); } int line_get_config(char *name, struct line *lines, unsigned int num, char *str, @@ -607,7 +594,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, spin_lock(&line->lock); if(!line->valid) CONFIG_CHUNK(str, size, n, "none", 1); - else if(line->tty == NULL) + else if(line->count == 0) CONFIG_CHUNK(str, size, n, line->init_str, 1); else n = chan_config_string(&line->chan_list, str, size, error_out); spin_unlock(&line->lock); @@ -632,18 +619,14 @@ int line_id(char **str, int *start_out, int *end_out) int line_remove(struct line *lines, unsigned int num, int n) { - int err; char config[sizeof("conxxxx=none\0")]; sprintf(config, "%d=none", n); - err = line_setup(lines, num, config); - if(err >= 0) - err = 0; - return err; + return !line_setup(lines, num, config, 0); } struct tty_driver *line_register_devfs(struct lines *set, - struct line_driver *line_driver, + struct line_driver *line_driver, struct tty_operations *ops, struct line *lines, int nlines) { @@ -672,7 +655,7 @@ struct tty_driver *line_register_devfs(struct lines *set, } for(i = 0; i < nlines; i++){ - if(!lines[i].valid) + if(!lines[i].valid) tty_unregister_device(driver, i); } @@ -680,28 +663,24 @@ struct tty_driver *line_register_devfs(struct lines *set, return driver; } -static DEFINE_SPINLOCK(winch_handler_lock); -static LIST_HEAD(winch_handlers); +static spinlock_t winch_handler_lock; +LIST_HEAD(winch_handlers); -void lines_init(struct line *lines, int nlines, struct chan_opts *opts) +void lines_init(struct line *lines, int nlines) { struct line *line; int i; + spin_lock_init(&winch_handler_lock); for(i = 0; i < nlines; i++){ line = &lines[i]; INIT_LIST_HEAD(&line->chan_list); - - if(line->init_str == NULL) - continue; - - line->init_str = kstrdup(line->init_str, GFP_KERNEL); - if(line->init_str == NULL) - printk("lines_init - kstrdup returned NULL\n"); - - if(parse_chan_pair(line->init_str, line, i, opts)){ - printk("parse_chan_pair failed for device %d\n", i); - line->valid = 0; + spin_lock_init(&line->lock); + if(line->init_str != NULL){ + line->init_str = uml_strdup(line->init_str); + if(line->init_str == NULL) + printk("lines_init - uml_strdup returned " + "NULL\n"); } } } @@ -738,7 +717,8 @@ irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused) tty = winch->tty; if (tty != NULL) { line = tty->driver_data; - chan_window_size(&line->chan_list, &tty->winsize.ws_row, + chan_window_size(&line->chan_list, + &tty->winsize.ws_row, &tty->winsize.ws_col); kill_pg(tty->pgrp, SIGWINCH, 1); } @@ -769,54 +749,60 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) spin_unlock(&winch_handler_lock); if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, - SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, + SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, "winch", winch) < 0) printk("register_winch_irq - failed to register IRQ\n"); } -static void free_winch(struct winch *winch) -{ - list_del(&winch->list); - - if(winch->pid != -1) - os_kill_process(winch->pid, 1); - if(winch->fd != -1) - os_close_file(winch->fd); - - free_irq(WINCH_IRQ, winch); - kfree(winch); -} - static void unregister_winch(struct tty_struct *tty) { struct list_head *ele; - struct winch *winch; + struct winch *winch, *found = NULL; spin_lock(&winch_handler_lock); - list_for_each(ele, &winch_handlers){ winch = list_entry(ele, struct winch, list); if(winch->tty == tty){ - free_winch(winch); - break; + found = winch; + break; } } + if(found == NULL) + goto err; + + list_del(&winch->list); + spin_unlock(&winch_handler_lock); + + if(winch->pid != -1) + os_kill_process(winch->pid, 1); + + free_irq(WINCH_IRQ, winch); + kfree(winch); + + return; +err: spin_unlock(&winch_handler_lock); } +/* XXX: No lock as it's an exitcall... is this valid? Depending on cleanup + * order... are we sure that nothing else is done on the list? */ static void winch_cleanup(void) { - struct list_head *ele, *next; + struct list_head *ele; struct winch *winch; - spin_lock(&winch_handler_lock); - - list_for_each_safe(ele, next, &winch_handlers){ + list_for_each(ele, &winch_handlers){ winch = list_entry(ele, struct winch, list); - free_winch(winch); + if(winch->fd != -1){ + /* Why is this different from the above free_irq(), + * which deactivates SIGIO? This searches the FD + * somewhere else and removes it from the list... */ + deactivate_fd(winch->fd, WINCH_IRQ); + os_close_file(winch->fd); + } + if(winch->pid != -1) + os_kill_process(winch->pid, 1); } - - spin_unlock(&winch_handler_lock); } __uml_exitcall(winch_cleanup); @@ -825,10 +811,10 @@ char *add_xterm_umid(char *base) char *umid, *title; int len; - umid = get_umid(); - if(*umid == '\0') + umid = get_umid(1); + if(umid == NULL) return base; - + len = strlen(base) + strlen(" ()") + strlen(umid) + 1; title = kmalloc(len, GFP_KERNEL); if(title == NULL){ diff --git a/trunk/arch/um/drivers/mconsole_kern.c b/trunk/arch/um/drivers/mconsole_kern.c index be610125429f..12c95368124a 100644 --- a/trunk/arch/um/drivers/mconsole_kern.c +++ b/trunk/arch/um/drivers/mconsole_kern.c @@ -20,7 +20,6 @@ #include "linux/namei.h" #include "linux/proc_fs.h" #include "linux/syscalls.h" -#include "linux/console.h" #include "asm/irq.h" #include "asm/uaccess.h" #include "user_util.h" @@ -35,7 +34,7 @@ #include "irq_kern.h" #include "choose-mode.h" -static int do_unlink_socket(struct notifier_block *notifier, +static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) { return(mconsole_unlink_socket()); @@ -47,12 +46,12 @@ static struct notifier_block reboot_notifier = { .priority = 0, }; -/* Safe without explicit locking for now. Tasklets provide their own +/* Safe without explicit locking for now. Tasklets provide their own * locking, and the interrupt handler is safe because it can't interrupt * itself and it can only happen on CPU 0. */ -static LIST_HEAD(mc_requests); +LIST_HEAD(mc_requests); static void mc_work_proc(void *unused) { @@ -61,7 +60,7 @@ static void mc_work_proc(void *unused) while(!list_empty(&mc_requests)){ local_save_flags(flags); - req = list_entry(mc_requests.next, struct mconsole_entry, + req = list_entry(mc_requests.next, struct mconsole_entry, list); list_del(&req->list); local_irq_restore(flags); @@ -70,7 +69,7 @@ static void mc_work_proc(void *unused) } } -static DECLARE_WORK(mconsole_work, mc_work_proc, NULL); +DECLARE_WORK(mconsole_work, mc_work_proc, NULL); static irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -104,8 +103,8 @@ void mconsole_version(struct mc_request *req) { char version[256]; - sprintf(version, "%s %s %s %s %s", system_utsname.sysname, - system_utsname.nodename, system_utsname.release, + sprintf(version, "%s %s %s %s %s", system_utsname.sysname, + system_utsname.nodename, system_utsname.release, system_utsname.version, system_utsname.machine); mconsole_reply(req, version, 0, 0); } @@ -349,7 +348,7 @@ static struct mc_device *mconsole_find_dev(char *name) #define CONFIG_BUF_SIZE 64 -static void mconsole_get_config(int (*get_config)(char *, char *, int, +static void mconsole_get_config(int (*get_config)(char *, char *, int, char **), struct mc_request *req, char *name) { @@ -390,6 +389,7 @@ static void mconsole_get_config(int (*get_config)(char *, char *, int, out: if(buf != default_buf) kfree(buf); + } void mconsole_config(struct mc_request *req) @@ -420,9 +420,9 @@ void mconsole_config(struct mc_request *req) void mconsole_remove(struct mc_request *req) { - struct mc_device *dev; + struct mc_device *dev; char *ptr = req->request.data, *err_msg = ""; - char error[256]; + char error[256]; int err, start, end, n; ptr += strlen("remove"); @@ -433,112 +433,37 @@ void mconsole_remove(struct mc_request *req) return; } - ptr = &ptr[strlen(dev->name)]; - - err = 1; - n = (*dev->id)(&ptr, &start, &end); - if(n < 0){ - err_msg = "Couldn't parse device number"; - goto out; - } - else if((n < start) || (n > end)){ - sprintf(error, "Invalid device number - must be between " - "%d and %d", start, end); - err_msg = error; - goto out; - } + ptr = &ptr[strlen(dev->name)]; + + err = 1; + n = (*dev->id)(&ptr, &start, &end); + if(n < 0){ + err_msg = "Couldn't parse device number"; + goto out; + } + else if((n < start) || (n > end)){ + sprintf(error, "Invalid device number - must be between " + "%d and %d", start, end); + err_msg = error; + goto out; + } err = (*dev->remove)(n); - switch(err){ - case -ENODEV: - err_msg = "Device doesn't exist"; - break; - case -EBUSY: - err_msg = "Device is currently open"; - break; - default: - break; - } -out: + switch(err){ + case -ENODEV: + err_msg = "Device doesn't exist"; + break; + case -EBUSY: + err_msg = "Device is currently open"; + break; + default: + break; + } + out: mconsole_reply(req, err_msg, err, 0); } -static DEFINE_SPINLOCK(console_lock); -static LIST_HEAD(clients); -static char console_buf[MCONSOLE_MAX_DATA]; -static int console_index = 0; - -static void console_write(struct console *console, const char *string, - unsigned len) -{ - struct list_head *ele; - int n; - - if(list_empty(&clients)) - return; - - while(1){ - n = min(len, ARRAY_SIZE(console_buf) - console_index); - strncpy(&console_buf[console_index], string, n); - console_index += n; - string += n; - len -= n; - if(len == 0) - return; - - list_for_each(ele, &clients){ - struct mconsole_entry *entry; - - entry = list_entry(ele, struct mconsole_entry, list); - mconsole_reply_len(&entry->request, console_buf, - console_index, 0, 1); - } - - console_index = 0; - } -} - -static struct console mc_console = { .name = "mc", - .write = console_write, - .flags = CON_PRINTBUFFER | CON_ENABLED, - .index = -1 }; - -static int mc_add_console(void) -{ - register_console(&mc_console); - return 0; -} - -late_initcall(mc_add_console); - -static void with_console(struct mc_request *req, void (*proc)(void *), - void *arg) -{ - struct mconsole_entry entry; - unsigned long flags; - - INIT_LIST_HEAD(&entry.list); - entry.request = *req; - list_add(&entry.list, &clients); - spin_lock_irqsave(&console_lock, flags); - - (*proc)(arg); - - mconsole_reply_len(req, console_buf, console_index, 0, 0); - console_index = 0; - - spin_unlock_irqrestore(&console_lock, flags); - list_del(&entry.list); -} - #ifdef CONFIG_MAGIC_SYSRQ -static void sysrq_proc(void *arg) -{ - char *op = arg; - - handle_sysrq(*op, ¤t->thread.regs, NULL); -} - void mconsole_sysrq(struct mc_request *req) { char *ptr = req->request.data; @@ -546,13 +471,8 @@ void mconsole_sysrq(struct mc_request *req) ptr += strlen("sysrq"); while(isspace(*ptr)) ptr++; - /* With 'b', the system will shut down without a chance to reply, - * so in this case, we reply first. - */ - if(*ptr == 'b') - mconsole_reply(req, "", 0, 0); - - with_console(req, sysrq_proc, ptr); + mconsole_reply(req, "", 0, 0); + handle_sysrq(*ptr, ¤t->thread.regs, NULL); } #else void mconsole_sysrq(struct mc_request *req) @@ -561,14 +481,6 @@ void mconsole_sysrq(struct mc_request *req) } #endif -static void stack_proc(void *arg) -{ - struct task_struct *from = current, *to = arg; - - to->thread.saved_task = from; - switch_to(from, to, from); -} - /* Mconsole stack trace * Added by Allan Graves, Jeff Dike * Dumps a stacks registers to the linux console. @@ -576,34 +488,37 @@ static void stack_proc(void *arg) */ void do_stack(struct mc_request *req) { - char *ptr = req->request.data; - int pid_requested= -1; - struct task_struct *from = NULL; + char *ptr = req->request.data; + int pid_requested= -1; + struct task_struct *from = NULL; struct task_struct *to = NULL; - /* Would be nice: - * 1) Send showregs output to mconsole. + /* Would be nice: + * 1) Send showregs output to mconsole. * 2) Add a way to stack dump all pids. */ - ptr += strlen("stack"); - while(isspace(*ptr)) ptr++; + ptr += strlen("stack"); + while(isspace(*ptr)) ptr++; - /* Should really check for multiple pids or reject bad args here */ - /* What do the arguments in mconsole_reply mean? */ - if(sscanf(ptr, "%d", &pid_requested) == 0){ - mconsole_reply(req, "Please specify a pid", 1, 0); - return; - } + /* Should really check for multiple pids or reject bad args here */ + /* What do the arguments in mconsole_reply mean? */ + if(sscanf(ptr, "%d", &pid_requested) == 0){ + mconsole_reply(req, "Please specify a pid", 1, 0); + return; + } - from = current; + from = current; + to = find_task_by_pid(pid_requested); - to = find_task_by_pid(pid_requested); - if((to == NULL) || (pid_requested == 0)) { - mconsole_reply(req, "Couldn't find that pid", 1, 0); - return; - } - with_console(req, stack_proc, to); + if((to == NULL) || (pid_requested == 0)) { + mconsole_reply(req, "Couldn't find that pid", 1, 0); + return; + } + to->thread.saved_task = current; + + switch_to(from, to, from); + mconsole_reply(req, "Stack Dumped to console and message log", 0, 0); } void mconsole_stack(struct mc_request *req) @@ -619,9 +534,9 @@ void mconsole_stack(struct mc_request *req) /* Changed by mconsole_setup, which is __setup, and called before SMP is * active. */ -static char *notify_socket = NULL; +static char *notify_socket = NULL; -static int mconsole_init(void) +int mconsole_init(void) { /* long to avoid size mismatch warnings from gcc */ long sock; @@ -648,16 +563,16 @@ static int mconsole_init(void) } if(notify_socket != NULL){ - notify_socket = kstrdup(notify_socket, GFP_KERNEL); + notify_socket = uml_strdup(notify_socket); if(notify_socket != NULL) mconsole_notify(notify_socket, MCONSOLE_SOCKET, - mconsole_socket_name, + mconsole_socket_name, strlen(mconsole_socket_name) + 1); else printk(KERN_ERR "mconsole_setup failed to strdup " "string\n"); } - printk("mconsole (version %d) initialized on %s\n", + printk("mconsole (version %d) initialized on %s\n", MCONSOLE_VERSION, mconsole_socket_name); return(0); } @@ -670,7 +585,7 @@ static int write_proc_mconsole(struct file *file, const char __user *buffer, char *buf; buf = kmalloc(count + 1, GFP_KERNEL); - if(buf == NULL) + if(buf == NULL) return(-ENOMEM); if(copy_from_user(buf, buffer, count)){ @@ -746,7 +661,7 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1, if(notify_socket == NULL) return(0); - mconsole_notify(notify_socket, MCONSOLE_PANIC, message, + mconsole_notify(notify_socket, MCONSOLE_PANIC, message, strlen(message) + 1); return(0); } @@ -771,3 +686,14 @@ char *mconsole_notify_socket(void) } EXPORT_SYMBOL(mconsole_notify_socket); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/drivers/mconsole_user.c b/trunk/arch/um/drivers/mconsole_user.c index 4b109fe7fff8..310c1f823f26 100644 --- a/trunk/arch/um/drivers/mconsole_user.c +++ b/trunk/arch/um/drivers/mconsole_user.c @@ -122,12 +122,12 @@ int mconsole_get_request(int fd, struct mc_request *req) return(1); } -int mconsole_reply_len(struct mc_request *req, const char *str, int total, - int err, int more) +int mconsole_reply(struct mc_request *req, char *str, int err, int more) { struct mconsole_reply reply; - int len, n; + int total, len, n; + total = strlen(str); do { reply.err = err; @@ -155,12 +155,6 @@ int mconsole_reply_len(struct mc_request *req, const char *str, int total, return(0); } -int mconsole_reply(struct mc_request *req, const char *str, int err, int more) -{ - return mconsole_reply_len(req, str, strlen(str), err, more); -} - - int mconsole_unlink_socket(void) { unlink(mconsole_socket_name); diff --git a/trunk/arch/um/drivers/net_kern.c b/trunk/arch/um/drivers/net_kern.c index fb1f9fb9b871..84c73a300acb 100644 --- a/trunk/arch/um/drivers/net_kern.c +++ b/trunk/arch/um/drivers/net_kern.c @@ -34,7 +34,7 @@ #define DRIVER_NAME "uml-netdev" static DEFINE_SPINLOCK(opened_lock); -static LIST_HEAD(opened); +LIST_HEAD(opened); static int uml_net_rx(struct net_device *dev) { @@ -150,7 +150,6 @@ static int uml_net_close(struct net_device *dev) if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; - list_del(&lp->list); spin_unlock(&lp->lock); return 0; @@ -267,7 +266,7 @@ void uml_net_user_timer_expire(unsigned long _conn) } static DEFINE_SPINLOCK(devices_lock); -static LIST_HEAD(devices); +static struct list_head devices = LIST_HEAD_INIT(devices); static struct platform_driver uml_net_driver = { .driver = { @@ -587,7 +586,7 @@ static int net_config(char *str) err = eth_parse(str, &n, &str); if(err) return(err); - str = kstrdup(str, GFP_KERNEL); + str = uml_strdup(str); if(str == NULL){ printk(KERN_ERR "net_config failed to strdup string\n"); return(-1); @@ -716,7 +715,6 @@ static void close_devices(void) list_for_each(ele, &opened){ lp = list_entry(ele, struct uml_net_private, list); - free_irq(lp->dev->irq, lp->dev); if((lp->close != NULL) && (lp->fd >= 0)) (*lp->close)(lp->fd, &lp->user); if(lp->remove != NULL) (*lp->remove)(&lp->user); diff --git a/trunk/arch/um/drivers/ssl.c b/trunk/arch/um/drivers/ssl.c index a32ef55cb244..62e04ecfada8 100644 --- a/trunk/arch/um/drivers/ssl.c +++ b/trunk/arch/um/drivers/ssl.c @@ -69,7 +69,7 @@ static struct line_driver driver = { .name = "ssl", .config = ssl_config, .get_config = ssl_get_config, - .id = line_id, + .id = line_id, .remove = ssl_remove, }, }; @@ -84,23 +84,26 @@ static struct lines lines = LINES_INIT(NR_PORTS); static int ssl_config(char *str) { - return line_config(serial_lines, ARRAY_SIZE(serial_lines), str, &opts); + return(line_config(serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0]), str)); } static int ssl_get_config(char *dev, char *str, int size, char **error_out) { - return line_get_config(dev, serial_lines, ARRAY_SIZE(serial_lines), str, - size, error_out); + return(line_get_config(dev, serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0]), + str, size, error_out)); } static int ssl_remove(int n) { - return line_remove(serial_lines, ARRAY_SIZE(serial_lines), n); + return line_remove(serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0]), n); } int ssl_open(struct tty_struct *tty, struct file *filp) { - return line_open(serial_lines, tty); + return line_open(serial_lines, tty, &opts); } #if 0 @@ -109,6 +112,16 @@ static void ssl_flush_buffer(struct tty_struct *tty) return; } +static void ssl_throttle(struct tty_struct * tty) +{ + printk(KERN_ERR "Someone should implement ssl_throttle\n"); +} + +static void ssl_unthrottle(struct tty_struct * tty) +{ + printk(KERN_ERR "Someone should implement ssl_unthrottle\n"); +} + static void ssl_stop(struct tty_struct *tty) { printk(KERN_ERR "Someone should implement ssl_stop\n"); @@ -135,9 +148,9 @@ static struct tty_operations ssl_ops = { .flush_chars = line_flush_chars, .set_termios = line_set_termios, .ioctl = line_ioctl, - .throttle = line_throttle, - .unthrottle = line_unthrottle, #if 0 + .throttle = ssl_throttle, + .unthrottle = ssl_unthrottle, .stop = ssl_stop, .start = ssl_start, .hangup = ssl_hangup, @@ -170,7 +183,7 @@ static int ssl_console_setup(struct console *co, char *options) { struct line *line = &serial_lines[co->index]; - return console_open_chan(line, co, &opts); + return console_open_chan(line,co,&opts); } static struct console ssl_cons = { @@ -186,13 +199,12 @@ int ssl_init(void) { char *new_title; - printk(KERN_INFO "Initializing software serial port version %d\n", + printk(KERN_INFO "Initializing software serial port version %d\n", ssl_version); ssl_driver = line_register_devfs(&lines, &driver, &ssl_ops, - serial_lines, - ARRAY_SIZE(serial_lines)); + serial_lines, ARRAY_SIZE(serial_lines)); - lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts); + lines_init(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0])); new_title = add_xterm_umid(opts.xterm_title); if (new_title != NULL) @@ -200,7 +212,7 @@ int ssl_init(void) ssl_init_done = 1; register_console(&ssl_cons); - return 0; + return(0); } late_initcall(ssl_init); @@ -208,13 +220,16 @@ static void ssl_exit(void) { if (!ssl_init_done) return; - close_lines(serial_lines, ARRAY_SIZE(serial_lines)); + close_lines(serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0])); } __uml_exitcall(ssl_exit); static int ssl_chan_setup(char *str) { - return line_setup(serial_lines, ARRAY_SIZE(serial_lines), str); + return(line_setup(serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0]), + str, 1)); } __setup("ssl", ssl_chan_setup); diff --git a/trunk/arch/um/drivers/stdio_console.c b/trunk/arch/um/drivers/stdio_console.c index 61db8b2fc83f..005aa6333b6e 100644 --- a/trunk/arch/um/drivers/stdio_console.c +++ b/trunk/arch/um/drivers/stdio_console.c @@ -75,7 +75,7 @@ static struct line_driver driver = { .name = "con", .config = con_config, .get_config = con_get_config, - .id = line_id, + .id = line_id, .remove = con_remove, }, }; @@ -86,27 +86,28 @@ static struct lines console_lines = LINES_INIT(MAX_TTYS); * individual elements are protected by individual semaphores. */ struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), - [ 1 ... MAX_TTYS - 1 ] = + [ 1 ... MAX_TTYS - 1 ] = LINE_INIT(CONFIG_CON_CHAN, &driver) }; static int con_config(char *str) { - return line_config(vts, ARRAY_SIZE(vts), str, &opts); + return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str)); } static int con_get_config(char *dev, char *str, int size, char **error_out) { - return line_get_config(dev, vts, ARRAY_SIZE(vts), str, size, error_out); + return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str, + size, error_out)); } static int con_remove(int n) { - return line_remove(vts, ARRAY_SIZE(vts), n); + return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n); } static int con_open(struct tty_struct *tty, struct file *filp) { - return line_open(vts, tty); + return line_open(vts, tty, &opts); } static int con_init_done = 0; @@ -116,18 +117,16 @@ static struct tty_operations console_ops = { .close = line_close, .write = line_write, .put_char = line_put_char, - .write_room = line_write_room, + .write_room = line_write_room, .chars_in_buffer = line_chars_in_buffer, .flush_buffer = line_flush_buffer, .flush_chars = line_flush_chars, .set_termios = line_set_termios, .ioctl = line_ioctl, - .throttle = line_throttle, - .unthrottle = line_unthrottle, }; static void uml_console_write(struct console *console, const char *string, - unsigned len) + unsigned len) { struct line *line = &vts[console->index]; unsigned long flags; @@ -147,7 +146,7 @@ static int uml_console_setup(struct console *co, char *options) { struct line *line = &vts[co->index]; - return console_open_chan(line, co, &opts); + return console_open_chan(line,co,&opts); } static struct console stdiocons = { @@ -157,7 +156,7 @@ static struct console stdiocons = { .setup = uml_console_setup, .flags = CON_PRINTBUFFER, .index = -1, - .data = &vts, + .data = &vts, }; int stdio_init(void) @@ -167,11 +166,11 @@ int stdio_init(void) console_driver = line_register_devfs(&console_lines, &driver, &console_ops, vts, ARRAY_SIZE(vts)); - if (console_driver == NULL) + if (NULL == console_driver) return -1; printk(KERN_INFO "Initialized stdio console driver\n"); - lines_init(vts, ARRAY_SIZE(vts), &opts); + lines_init(vts, sizeof(vts)/sizeof(vts[0])); new_title = add_xterm_umid(opts.xterm_title); if(new_title != NULL) @@ -179,7 +178,7 @@ int stdio_init(void) con_init_done = 1; register_console(&stdiocons); - return 0; + return(0); } late_initcall(stdio_init); @@ -187,13 +186,13 @@ static void console_exit(void) { if (!con_init_done) return; - close_lines(vts, ARRAY_SIZE(vts)); + close_lines(vts, sizeof(vts)/sizeof(vts[0])); } __uml_exitcall(console_exit); static int console_chan_setup(char *str) { - return line_setup(vts, ARRAY_SIZE(vts), str); + return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); } __setup("con", console_chan_setup); __channel_help(console_chan_setup, "con"); diff --git a/trunk/arch/um/drivers/ubd_kern.c b/trunk/arch/um/drivers/ubd_kern.c index 73f9652b2ee9..93898917cbe5 100644 --- a/trunk/arch/um/drivers/ubd_kern.c +++ b/trunk/arch/um/drivers/ubd_kern.c @@ -706,7 +706,7 @@ static int ubd_config(char *str) { int n, err; - str = kstrdup(str, GFP_KERNEL); + str = uml_strdup(str); if(str == NULL){ printk(KERN_ERR "ubd_config failed to strdup string\n"); return(1); @@ -1387,6 +1387,15 @@ int io_thread(void *arg) printk("io_thread - write failed, fd = %d, err = %d\n", kernel_fd, -n); } - - return 0; } + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/chan_kern.h b/trunk/arch/um/include/chan_kern.h index 1bb5e9d94270..da9a6717e7a4 100644 --- a/trunk/arch/um/include/chan_kern.h +++ b/trunk/arch/um/include/chan_kern.h @@ -14,23 +14,21 @@ struct chan { struct list_head list; - struct list_head free_list; - struct line *line; char *dev; unsigned int primary:1; unsigned int input:1; unsigned int output:1; unsigned int opened:1; - unsigned int enabled:1; int fd; + enum chan_init_pri pri; struct chan_ops *ops; void *data; }; extern void chan_interrupt(struct list_head *chans, struct work_struct *task, struct tty_struct *tty, int irq); -extern int parse_chan_pair(char *str, struct line *line, int device, - struct chan_opts *opts); +extern int parse_chan_pair(char *str, struct list_head *chans, int pri, + int device, struct chan_opts *opts); extern int open_chan(struct list_head *chans); extern int write_chan(struct list_head *chans, const char *buf, int len, int write_irq); @@ -38,11 +36,9 @@ extern int console_write_chan(struct list_head *chans, const char *buf, int len); extern int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts); -extern void deactivate_chan(struct list_head *chans, int irq); -extern void reactivate_chan(struct list_head *chans, int irq); +extern void close_chan(struct list_head *chans); extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); -extern void enable_chan(struct line *line); -extern void close_chan(struct list_head *chans, int delay_free_irq); +extern void enable_chan(struct list_head *chans, struct tty_struct *tty); extern int chan_window_size(struct list_head *chans, unsigned short *rows_out, unsigned short *cols_out); @@ -51,3 +47,14 @@ extern int chan_config_string(struct list_head *chans, char *str, int size, char **error_out); #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/choose-mode.h b/trunk/arch/um/include/choose-mode.h index b87b36a87d91..f25fa83a5da6 100644 --- a/trunk/arch/um/include/choose-mode.h +++ b/trunk/arch/um/include/choose-mode.h @@ -23,9 +23,6 @@ static inline void *__choose_mode(void *tt, void *skas) { #elif defined(UML_CONFIG_MODE_TT) #define CHOOSE_MODE(tt, skas) (tt) - -#else -#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled #endif #define CHOOSE_MODE_PROC(tt, skas, args...) \ diff --git a/trunk/arch/um/include/irq_user.h b/trunk/arch/um/include/irq_user.h index b61deb8b362a..f724b717213f 100644 --- a/trunk/arch/um/include/irq_user.h +++ b/trunk/arch/um/include/irq_user.h @@ -18,8 +18,19 @@ extern int deactivate_all_fds(void); extern void forward_interrupts(int pid); extern void init_irq_signals(int on_sigstack); extern void forward_ipi(int fd, int pid); +extern void free_irq_later(int irq, void *dev_id); extern int activate_ipi(int fd, int pid); extern unsigned long irq_lock(void); extern void irq_unlock(unsigned long flags); - #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/kern.h b/trunk/arch/um/include/kern.h index 7d223beccbc0..1e3170768b5c 100644 --- a/trunk/arch/um/include/kern.h +++ b/trunk/arch/um/include/kern.h @@ -17,7 +17,7 @@ extern int errno; extern int clone(int (*proc)(void *), void *sp, int flags, void *data); extern int sleep(int); -extern int printf(const char *fmt, ...); +extern int printf(char *fmt, ...); extern char *strerror(int errnum); extern char *ptsname(int __fd); extern int munmap(void *, int); @@ -35,6 +35,15 @@ extern int read(unsigned int, char *, int); extern int pipe(int *); extern int sched_yield(void); extern int ptrace(int op, int pid, long addr, long data); - #endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/line.h b/trunk/arch/um/include/line.h index 6f4d680dc1d4..5323d22a6ca7 100644 --- a/trunk/arch/um/include/line.h +++ b/trunk/arch/um/include/line.h @@ -32,13 +32,11 @@ struct line_driver { }; struct line { - struct tty_struct *tty; char *init_str; int init_pri; struct list_head chan_list; int valid; int count; - int throttled; /*This lock is actually, mostly, local to*/ spinlock_t lock; @@ -60,15 +58,14 @@ struct line { #define LINE_INIT(str, d) \ { init_str : str, \ init_pri : INIT_STATIC, \ + chan_list : { }, \ valid : 1, \ - throttled : 0, \ - lock : SPIN_LOCK_UNLOCKED, \ buffer : NULL, \ head : NULL, \ tail : NULL, \ sigio : 0, \ - driver : d, \ - have_irq : 0 } + driver : d, \ + have_irq : 0 } struct lines { int num; @@ -77,11 +74,11 @@ struct lines { #define LINES_INIT(n) { num : n } extern void line_close(struct tty_struct *tty, struct file * filp); -extern int line_open(struct line *lines, struct tty_struct *tty); -extern int line_setup(struct line *lines, unsigned int sizeof_lines, - char *init); -extern int line_write(struct tty_struct *tty, const unsigned char *buf, - int len); +extern int line_open(struct line *lines, struct tty_struct *tty, + struct chan_opts *opts); +extern int line_setup(struct line *lines, unsigned int sizeof_lines, char *init, + int all_allowed); +extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); extern void line_put_char(struct tty_struct *tty, unsigned char ch); extern void line_set_termios(struct tty_struct *tty, struct termios * old); extern int line_chars_in_buffer(struct tty_struct *tty); @@ -90,27 +87,23 @@ extern void line_flush_chars(struct tty_struct *tty); extern int line_write_room(struct tty_struct *tty); extern int line_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); -extern void line_throttle(struct tty_struct *tty); -extern void line_unthrottle(struct tty_struct *tty); extern char *add_xterm_umid(char *base); -extern int line_setup_irq(int fd, int input, int output, struct line *line, - void *data); +extern int line_setup_irq(int fd, int input, int output, struct tty_struct *tty); extern void line_close_chan(struct line *line); -extern struct tty_driver * line_register_devfs(struct lines *set, - struct line_driver *line_driver, +extern void line_disable(struct tty_struct *tty, int current_irq); +extern struct tty_driver * line_register_devfs(struct lines *set, + struct line_driver *line_driver, struct tty_operations *driver, struct line *lines, int nlines); -extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); +extern void lines_init(struct line *lines, int nlines); extern void close_lines(struct line *lines, int nlines); -extern int line_config(struct line *lines, unsigned int sizeof_lines, - char *str, struct chan_opts *opts); +extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str); extern int line_id(char **str, int *start_out, int *end_out); extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n); -extern int line_get_config(char *dev, struct line *lines, - unsigned int sizeof_lines, char *str, +extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str, int size, char **error_out); #endif diff --git a/trunk/arch/um/include/mconsole.h b/trunk/arch/um/include/mconsole.h index 58f67d391105..b1b512f47035 100644 --- a/trunk/arch/um/include/mconsole.h +++ b/trunk/arch/um/include/mconsole.h @@ -32,7 +32,7 @@ struct mconsole_reply { struct mconsole_notify { u32 magic; - u32 version; + u32 version; enum { MCONSOLE_SOCKET, MCONSOLE_PANIC, MCONSOLE_HANG, MCONSOLE_USER_NOTIFY } type; u32 len; @@ -66,9 +66,7 @@ struct mc_request extern char mconsole_socket_name[]; extern int mconsole_unlink_socket(void); -extern int mconsole_reply_len(struct mc_request *req, const char *reply, - int len, int err, int more); -extern int mconsole_reply(struct mc_request *req, const char *str, int err, +extern int mconsole_reply(struct mc_request *req, char *reply, int err, int more); extern void mconsole_version(struct mc_request *req); @@ -86,7 +84,7 @@ extern void mconsole_proc(struct mc_request *req); extern void mconsole_stack(struct mc_request *req); extern int mconsole_get_request(int fd, struct mc_request *req); -extern int mconsole_notify(char *sock_name, int type, const void *data, +extern int mconsole_notify(char *sock_name, int type, const void *data, int len); extern char *mconsole_notify_socket(void); extern void lock_notify(void); diff --git a/trunk/arch/um/include/os.h b/trunk/arch/um/include/os.h index c279ee6d89e4..2cccfa5b8ab5 100644 --- a/trunk/arch/um/include/os.h +++ b/trunk/arch/um/include/os.h @@ -213,10 +213,15 @@ extern int run_helper_thread(int (*proc)(void *), void *arg, int stack_order); extern int helper_wait(int pid); -/* umid.c */ - -extern int umid_file_name(char *name, char *buf, int len); -extern int set_umid(char *name); -extern char *get_umid(void); - #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/include/user_util.h b/trunk/arch/um/include/user_util.h index b9984003e603..bb505e01d994 100644 --- a/trunk/arch/um/include/user_util.h +++ b/trunk/arch/um/include/user_util.h @@ -64,6 +64,7 @@ extern void setup_machinename(char *machine_out); extern void setup_hostinfo(void); extern void do_exec(int old_pid, int new_pid); extern void tracer_panic(char *msg, ...); +extern char *get_umid(int only_if_set); extern void do_longjmp(void *p, int val); extern int detach(int pid, int sig); extern int attach(int pid); diff --git a/trunk/arch/um/kernel/Makefile b/trunk/arch/um/kernel/Makefile index 6f7700593a6f..3de9d21e36bf 100644 --- a/trunk/arch/um/kernel/Makefile +++ b/trunk/arch/um/kernel/Makefile @@ -10,8 +10,8 @@ obj-y = config.o exec_kern.o exitcode.o \ init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ - time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o umid.o \ - user_util.o + time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ + umid.o user_util.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o @@ -24,7 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o +USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o include arch/um/scripts/Makefile.rules diff --git a/trunk/arch/um/kernel/irq_user.c b/trunk/arch/um/kernel/irq_user.c index 50a2aa35cda9..c3ccaf24f3e0 100644 --- a/trunk/arch/um/kernel/irq_user.c +++ b/trunk/arch/um/kernel/irq_user.c @@ -29,6 +29,7 @@ struct irq_fd { int pid; int events; int current_events; + int freed; }; static struct irq_fd *active_fds = NULL; @@ -40,11 +41,9 @@ static int pollfds_size = 0; extern int io_count, intr_count; -extern void free_irqs(void); - void sigio_handler(int sig, union uml_pt_regs *regs) { - struct irq_fd *irq_fd; + struct irq_fd *irq_fd, *next; int i, n; if(smp_sigio_handler()) return; @@ -67,15 +66,29 @@ void sigio_handler(int sig, union uml_pt_regs *regs) irq_fd = irq_fd->next; } - for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ + for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ + next = irq_fd->next; if(irq_fd->current_events != 0){ irq_fd->current_events = 0; do_IRQ(irq_fd->irq, regs); + + /* This is here because the next irq may be + * freed in the handler. If a console goes + * away, both the read and write irqs will be + * freed. After do_IRQ, ->next will point to + * a good IRQ. + * Irqs can't be freed inside their handlers, + * so the next best thing is to have them + * marked as needing freeing, so that they + * can be freed here. + */ + next = irq_fd->next; + if(irq_fd->freed){ + free_irq(irq_fd->irq, irq_fd->id); + } } } } - - free_irqs(); } int activate_ipi(int fd, int pid) @@ -123,7 +136,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id) .irq = irq, .pid = pid, .events = events, - .current_events = 0 } ); + .current_events = 0, + .freed = 0 } ); /* Critical section - locked by a spinlock because this stuff can * be changed from interrupt handlers. The stuff above is done @@ -299,6 +313,26 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) return(irq); } +void free_irq_later(int irq, void *dev_id) +{ + struct irq_fd *irq_fd; + unsigned long flags; + + flags = irq_lock(); + for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ + if((irq_fd->irq == irq) && (irq_fd->id == dev_id)) + break; + } + if(irq_fd == NULL){ + printk("free_irq_later found no irq, irq = %d, " + "dev_id = 0x%p\n", irq, dev_id); + goto out; + } + irq_fd->freed = 1; + out: + irq_unlock(flags); +} + void reactivate_fd(int fd, int irqnum) { struct irq_fd *irq; diff --git a/trunk/arch/um/kernel/process_kern.c b/trunk/arch/um/kernel/process_kern.c index 651abf255bc5..34b54a3e2132 100644 --- a/trunk/arch/um/kernel/process_kern.c +++ b/trunk/arch/um/kernel/process_kern.c @@ -324,6 +324,10 @@ int user_context(unsigned long sp) return(stack != (unsigned long) current_thread); } +extern void remove_umid_dir(void); + +__uml_exitcall(remove_umid_dir); + extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; void do_uml_exitcalls(void) diff --git a/trunk/arch/um/kernel/sigio_user.c b/trunk/arch/um/kernel/sigio_user.c index 62e5cfdf2188..48b1f644b9a6 100644 --- a/trunk/arch/um/kernel/sigio_user.c +++ b/trunk/arch/um/kernel/sigio_user.c @@ -216,8 +216,6 @@ static int write_sigio_thread(void *unused) "err = %d\n", -n); } } - - return 0; } static int need_poll(int n) diff --git a/trunk/arch/um/kernel/um_arch.c b/trunk/arch/um/kernel/um_arch.c index 26626b2b9172..142a9493912b 100644 --- a/trunk/arch/um/kernel/um_arch.c +++ b/trunk/arch/um/kernel/um_arch.c @@ -146,8 +146,8 @@ void set_cmdline(char *cmd) if(CHOOSE_MODE(honeypot, 0)) return; - umid = get_umid(); - if(*umid != '\0'){ + umid = get_umid(1); + if(umid != NULL){ snprintf(argv1_begin, (argv1_end - argv1_begin) * sizeof(*ptr), "(%s) ", umid); diff --git a/trunk/arch/um/kernel/umid.c b/trunk/arch/um/kernel/umid.c index 4eaee823bfd2..0b21d59ba0cd 100644 --- a/trunk/arch/um/kernel/umid.c +++ b/trunk/arch/um/kernel/umid.c @@ -3,35 +3,328 @@ * Licensed under the GPL */ -#include "asm/errno.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "user.h" +#include "umid.h" #include "init.h" #include "os.h" -#include "kern.h" -#include "linux/kernel.h" +#include "user_util.h" +#include "choose-mode.h" -/* Changed by set_umid_arg */ +#define UMID_LEN 64 +#define UML_DIR "~/.uml/" + +/* Changed by set_umid and make_umid, which are run early in boot */ +static char umid[UMID_LEN] = { 0 }; + +/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ +static char *uml_dir = UML_DIR; + +/* Changed by set_umid */ +static int umid_is_random = 1; static int umid_inited = 0; +/* Have we created the files? Should we remove them? */ +static int umid_owned = 0; -static int __init set_umid_arg(char *name, int *add) -{ - int err; +static int make_umid(int (*printer)(const char *fmt, ...)); - if(umid_inited) - return 0; +static int __init set_umid(char *name, int is_random, + int (*printer)(const char *fmt, ...)) +{ + if(umid_inited){ + (*printer)("Unique machine name can't be set twice\n"); + return(-1); + } - *add = 0; - err = set_umid(name); - if(err == -EEXIST) - printf("umid '%s' already in use\n", name); - else if(!err) - umid_inited = 1; + if(strlen(name) > UMID_LEN - 1) + (*printer)("Unique machine name is being truncated to %d " + "characters\n", UMID_LEN); + strlcpy(umid, name, sizeof(umid)); + umid_is_random = is_random; + umid_inited = 1; return 0; } +static int __init set_umid_arg(char *name, int *add) +{ + *add = 0; + return(set_umid(name, 0, printf)); +} + __uml_setup("umid=", set_umid_arg, "umid=\n" " This is used to assign a unique identity to this UML machine and\n" " is used for naming the pid file and management console socket.\n\n" ); +int __init umid_file_name(char *name, char *buf, int len) +{ + int n; + + if(!umid_inited && make_umid(printk)) return(-1); + + n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; + if(n > len){ + printk("umid_file_name : buffer too short\n"); + return(-1); + } + + sprintf(buf, "%s%s/%s", uml_dir, umid, name); + return(0); +} + +extern int tracing_pid; + +static void __init create_pid_file(void) +{ + char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; + char pid[sizeof("nnnnn\0")]; + int fd, n; + + if(umid_file_name("pid", file, sizeof(file))) + return; + + fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), + 0644); + if(fd < 0){ + printf("Open of machine pid file \"%s\" failed: %s\n", + file, strerror(-fd)); + return; + } + + sprintf(pid, "%d\n", os_getpid()); + n = os_write_file(fd, pid, strlen(pid)); + if(n != strlen(pid)) + printf("Write of pid file failed - err = %d\n", -n); + os_close_file(fd); +} + +static int actually_do_remove(char *dir) +{ + DIR *directory; + struct dirent *ent; + int len; + char file[256]; + + directory = opendir(dir); + if(directory == NULL){ + printk("actually_do_remove : couldn't open directory '%s', " + "errno = %d\n", dir, errno); + return(1); + } + while((ent = readdir(directory)) != NULL){ + if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) + continue; + len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; + if(len > sizeof(file)){ + printk("Not deleting '%s' from '%s' - name too long\n", + ent->d_name, dir); + continue; + } + sprintf(file, "%s/%s", dir, ent->d_name); + if(unlink(file) < 0){ + printk("actually_do_remove : couldn't remove '%s' " + "from '%s', errno = %d\n", ent->d_name, dir, + errno); + return(1); + } + } + if(rmdir(dir) < 0){ + printk("actually_do_remove : couldn't rmdir '%s', " + "errno = %d\n", dir, errno); + return(1); + } + return(0); +} + +void remove_umid_dir(void) +{ + char dir[strlen(uml_dir) + UMID_LEN + 1]; + if (!umid_owned) + return; + + sprintf(dir, "%s%s", uml_dir, umid); + actually_do_remove(dir); +} + +char *get_umid(int only_if_set) +{ + if(only_if_set && umid_is_random) + return NULL; + return umid; +} + +static int not_dead_yet(char *dir) +{ + char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; + char pid[sizeof("nnnnn\0")], *end; + int dead, fd, p, n; + + sprintf(file, "%s/pid", dir); + dead = 0; + fd = os_open_file(file, of_read(OPENFLAGS()), 0); + if(fd < 0){ + if(fd != -ENOENT){ + printk("not_dead_yet : couldn't open pid file '%s', " + "err = %d\n", file, -fd); + return(1); + } + dead = 1; + } + if(fd > 0){ + n = os_read_file(fd, pid, sizeof(pid)); + if(n < 0){ + printk("not_dead_yet : couldn't read pid file '%s', " + "err = %d\n", file, -n); + return(1); + } + p = strtoul(pid, &end, 0); + if(end == pid){ + printk("not_dead_yet : couldn't parse pid file '%s', " + "errno = %d\n", file, errno); + dead = 1; + } + if(((kill(p, 0) < 0) && (errno == ESRCH)) || + (p == CHOOSE_MODE(tracing_pid, os_getpid()))) + dead = 1; + } + if(!dead) + return(1); + return(actually_do_remove(dir)); +} + +static int __init set_uml_dir(char *name, int *add) +{ + if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ + uml_dir = malloc(strlen(name) + 2); + if(uml_dir == NULL){ + printf("Failed to malloc uml_dir - error = %d\n", + errno); + uml_dir = name; + /* Return 0 here because do_initcalls doesn't look at + * the return value. + */ + return(0); + } + sprintf(uml_dir, "%s/", name); + } + else uml_dir = name; + return(0); +} + +static int __init make_uml_dir(void) +{ + char dir[MAXPATHLEN + 1] = { '\0' }; + int len; + + if(*uml_dir == '~'){ + char *home = getenv("HOME"); + + if(home == NULL){ + printf("make_uml_dir : no value in environment for " + "$HOME\n"); + exit(1); + } + strlcpy(dir, home, sizeof(dir)); + uml_dir++; + } + strlcat(dir, uml_dir, sizeof(dir)); + len = strlen(dir); + if (len > 0 && dir[len - 1] != '/') + strlcat(dir, "/", sizeof(dir)); + + uml_dir = malloc(strlen(dir) + 1); + if (uml_dir == NULL) { + printf("make_uml_dir : malloc failed, errno = %d\n", errno); + exit(1); + } + strcpy(uml_dir, dir); + + if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ + printf("Failed to mkdir %s: %s\n", uml_dir, strerror(errno)); + return(-1); + } + return 0; +} + +static int __init make_umid(int (*printer)(const char *fmt, ...)) +{ + int fd, err; + char tmp[strlen(uml_dir) + UMID_LEN + 1]; + + strlcpy(tmp, uml_dir, sizeof(tmp)); + + if(!umid_inited){ + strcat(tmp, "XXXXXX"); + fd = mkstemp(tmp); + if(fd < 0){ + (*printer)("make_umid - mkstemp(%s) failed: %s\n", + tmp,strerror(errno)); + return(1); + } + + os_close_file(fd); + /* There's a nice tiny little race between this unlink and + * the mkdir below. It'd be nice if there were a mkstemp + * for directories. + */ + unlink(tmp); + set_umid(&tmp[strlen(uml_dir)], 1, printer); + } + + sprintf(tmp, "%s%s", uml_dir, umid); + + err = mkdir(tmp, 0777); + if(err < 0){ + if(errno == EEXIST){ + if(not_dead_yet(tmp)){ + (*printer)("umid '%s' is in use\n", umid); + umid_owned = 0; + return(-1); + } + err = mkdir(tmp, 0777); + } + } + if(err < 0){ + (*printer)("Failed to create %s - errno = %d\n", umid, errno); + return(-1); + } + + umid_owned = 1; + return 0; +} + +__uml_setup("uml_dir=", set_uml_dir, +"uml_dir=\n" +" The location to place the pid and umid files.\n\n" +); + +static int __init make_umid_setup(void) +{ + /* one function with the ordering we need ... */ + make_uml_dir(); + make_umid(printf); + create_pid_file(); + return 0; +} +__uml_postsetup(make_umid_setup); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/trunk/arch/um/os-Linux/Makefile b/trunk/arch/um/os-Linux/Makefile index 11e30b13e318..b83ac8e21c35 100644 --- a/trunk/arch/um/os-Linux/Makefile +++ b/trunk/arch/um/os-Linux/Makefile @@ -4,11 +4,11 @@ # obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ - start_up.o time.o tt.o tty.o uaccess.o umid.o user_syms.o drivers/ \ + start_up.o time.o tt.o tty.o uaccess.o user_syms.o drivers/ \ sys-$(SUBARCH)/ USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ - start_up.o time.o tt.o tty.o uaccess.o umid.o + start_up.o time.o tt.o tty.o uaccess.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/trunk/arch/um/os-Linux/aio.c b/trunk/arch/um/os-Linux/aio.c index f897140cc4ae..ffa759addd3c 100644 --- a/trunk/arch/um/os-Linux/aio.c +++ b/trunk/arch/um/os-Linux/aio.c @@ -16,12 +16,12 @@ #include "mode.h" struct aio_thread_req { - enum aio_type type; - int io_fd; - unsigned long long offset; - char *buf; - int len; - struct aio_context *aio; + enum aio_type type; + int io_fd; + unsigned long long offset; + char *buf; + int len; + struct aio_context *aio; }; static int aio_req_fd_r = -1; @@ -38,18 +38,18 @@ static int aio_req_fd_w = -1; static long io_setup(int n, aio_context_t *ctxp) { - return syscall(__NR_io_setup, n, ctxp); + return syscall(__NR_io_setup, n, ctxp); } static long io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) { - return syscall(__NR_io_submit, ctx, nr, iocbpp); + return syscall(__NR_io_submit, ctx, nr, iocbpp); } static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, - struct io_event *events, struct timespec *timeout) + struct io_event *events, struct timespec *timeout) { - return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout); + return syscall(__NR_io_getevents, ctx_id, min_nr, nr, events, timeout); } #endif @@ -66,245 +66,243 @@ static long io_getevents(aio_context_t ctx_id, long min_nr, long nr, */ static int do_aio(aio_context_t ctx, enum aio_type type, int fd, char *buf, - int len, unsigned long long offset, struct aio_context *aio) + int len, unsigned long long offset, struct aio_context *aio) { - struct iocb iocb, *iocbp = &iocb; - char c; - int err; - - iocb = ((struct iocb) { .aio_data = (unsigned long) aio, - .aio_reqprio = 0, - .aio_fildes = fd, - .aio_buf = (unsigned long) buf, - .aio_nbytes = len, - .aio_offset = offset, - .aio_reserved1 = 0, - .aio_reserved2 = 0, - .aio_reserved3 = 0 }); - - switch(type){ - case AIO_READ: - iocb.aio_lio_opcode = IOCB_CMD_PREAD; - err = io_submit(ctx, 1, &iocbp); - break; - case AIO_WRITE: - iocb.aio_lio_opcode = IOCB_CMD_PWRITE; - err = io_submit(ctx, 1, &iocbp); - break; - case AIO_MMAP: - iocb.aio_lio_opcode = IOCB_CMD_PREAD; - iocb.aio_buf = (unsigned long) &c; - iocb.aio_nbytes = sizeof(c); - err = io_submit(ctx, 1, &iocbp); - break; - default: - printk("Bogus op in do_aio - %d\n", type); - err = -EINVAL; - break; - } - - if(err > 0) - err = 0; + struct iocb iocb, *iocbp = &iocb; + char c; + int err; + + iocb = ((struct iocb) { .aio_data = (unsigned long) aio, + .aio_reqprio = 0, + .aio_fildes = fd, + .aio_buf = (unsigned long) buf, + .aio_nbytes = len, + .aio_offset = offset, + .aio_reserved1 = 0, + .aio_reserved2 = 0, + .aio_reserved3 = 0 }); + + switch(type){ + case AIO_READ: + iocb.aio_lio_opcode = IOCB_CMD_PREAD; + err = io_submit(ctx, 1, &iocbp); + break; + case AIO_WRITE: + iocb.aio_lio_opcode = IOCB_CMD_PWRITE; + err = io_submit(ctx, 1, &iocbp); + break; + case AIO_MMAP: + iocb.aio_lio_opcode = IOCB_CMD_PREAD; + iocb.aio_buf = (unsigned long) &c; + iocb.aio_nbytes = sizeof(c); + err = io_submit(ctx, 1, &iocbp); + break; + default: + printk("Bogus op in do_aio - %d\n", type); + err = -EINVAL; + break; + } + + if(err > 0) + err = 0; else err = -errno; - return err; + return err; } static aio_context_t ctx = 0; static int aio_thread(void *arg) { - struct aio_thread_reply reply; - struct io_event event; - int err, n, reply_fd; - - signal(SIGWINCH, SIG_IGN); - - while(1){ - n = io_getevents(ctx, 1, 1, &event, NULL); - if(n < 0){ - if(errno == EINTR) - continue; - printk("aio_thread - io_getevents failed, " - "errno = %d\n", errno); - } - else { - reply = ((struct aio_thread_reply) - { .data = (void *) (long) event.data, - .err = event.res }); + struct aio_thread_reply reply; + struct io_event event; + int err, n, reply_fd; + + signal(SIGWINCH, SIG_IGN); + + while(1){ + n = io_getevents(ctx, 1, 1, &event, NULL); + if(n < 0){ + if(errno == EINTR) + continue; + printk("aio_thread - io_getevents failed, " + "errno = %d\n", errno); + } + else { + reply = ((struct aio_thread_reply) + { .data = (void *) (long) event.data, + .err = event.res }); reply_fd = ((struct aio_context *) reply.data)->reply_fd; err = os_write_file(reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) + if(err != sizeof(reply)) printk("aio_thread - write failed, fd = %d, " - "err = %d\n", aio_req_fd_r, -err); - } - } - return 0; + "err = %d\n", aio_req_fd_r, -err); + } + } + return 0; } #endif static int do_not_aio(struct aio_thread_req *req) { - char c; - int err; - - switch(req->type){ - case AIO_READ: - err = os_seek_file(req->io_fd, req->offset); - if(err) - goto out; - - err = os_read_file(req->io_fd, req->buf, req->len); - break; - case AIO_WRITE: - err = os_seek_file(req->io_fd, req->offset); - if(err) - goto out; - - err = os_write_file(req->io_fd, req->buf, req->len); - break; - case AIO_MMAP: - err = os_seek_file(req->io_fd, req->offset); - if(err) - goto out; - - err = os_read_file(req->io_fd, &c, sizeof(c)); - break; - default: - printk("do_not_aio - bad request type : %d\n", req->type); - err = -EINVAL; - break; - } - -out: - return err; + char c; + int err; + + switch(req->type){ + case AIO_READ: + err = os_seek_file(req->io_fd, req->offset); + if(err) + goto out; + + err = os_read_file(req->io_fd, req->buf, req->len); + break; + case AIO_WRITE: + err = os_seek_file(req->io_fd, req->offset); + if(err) + goto out; + + err = os_write_file(req->io_fd, req->buf, req->len); + break; + case AIO_MMAP: + err = os_seek_file(req->io_fd, req->offset); + if(err) + goto out; + + err = os_read_file(req->io_fd, &c, sizeof(c)); + break; + default: + printk("do_not_aio - bad request type : %d\n", req->type); + err = -EINVAL; + break; + } + + out: + return err; } static int not_aio_thread(void *arg) { - struct aio_thread_req req; - struct aio_thread_reply reply; - int err; - - signal(SIGWINCH, SIG_IGN); - while(1){ - err = os_read_file(aio_req_fd_r, &req, sizeof(req)); - if(err != sizeof(req)){ - if(err < 0) - printk("not_aio_thread - read failed, " - "fd = %d, err = %d\n", aio_req_fd_r, - -err); - else { - printk("not_aio_thread - short read, fd = %d, " - "length = %d\n", aio_req_fd_r, err); - } - continue; - } - err = do_not_aio(&req); - reply = ((struct aio_thread_reply) { .data = req.aio, - .err = err }); - err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) - printk("not_aio_thread - write failed, fd = %d, " - "err = %d\n", aio_req_fd_r, -err); - } - - return 0; + struct aio_thread_req req; + struct aio_thread_reply reply; + int err; + + signal(SIGWINCH, SIG_IGN); + while(1){ + err = os_read_file(aio_req_fd_r, &req, sizeof(req)); + if(err != sizeof(req)){ + if(err < 0) + printk("not_aio_thread - read failed, " + "fd = %d, err = %d\n", aio_req_fd_r, + -err); + else { + printk("not_aio_thread - short read, fd = %d, " + "length = %d\n", aio_req_fd_r, err); + } + continue; + } + err = do_not_aio(&req); + reply = ((struct aio_thread_reply) { .data = req.aio, + .err = err }); + err = os_write_file(req.aio->reply_fd, &reply, sizeof(reply)); + if(err != sizeof(reply)) + printk("not_aio_thread - write failed, fd = %d, " + "err = %d\n", aio_req_fd_r, -err); + } } static int aio_pid = -1; static int init_aio_24(void) { - unsigned long stack; - int fds[2], err; - - err = os_pipe(fds, 1, 1); - if(err) - goto out; - - aio_req_fd_w = fds[0]; - aio_req_fd_r = fds[1]; - err = run_helper_thread(not_aio_thread, NULL, - CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); - if(err < 0) - goto out_close_pipe; - - aio_pid = err; - goto out; - -out_close_pipe: - os_close_file(fds[0]); - os_close_file(fds[1]); - aio_req_fd_w = -1; - aio_req_fd_r = -1; -out: + unsigned long stack; + int fds[2], err; + + err = os_pipe(fds, 1, 1); + if(err) + goto out; + + aio_req_fd_w = fds[0]; + aio_req_fd_r = fds[1]; + err = run_helper_thread(not_aio_thread, NULL, + CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); + if(err < 0) + goto out_close_pipe; + + aio_pid = err; + goto out; + + out_close_pipe: + os_close_file(fds[0]); + os_close_file(fds[1]); + aio_req_fd_w = -1; + aio_req_fd_r = -1; + out: #ifndef HAVE_AIO_ABI printk("/usr/include/linux/aio_abi.h not present during build\n"); #endif printk("2.6 host AIO support not used - falling back to I/O " "thread\n"); - return 0; + return 0; } #ifdef HAVE_AIO_ABI #define DEFAULT_24_AIO 0 static int init_aio_26(void) { - unsigned long stack; - int err; + unsigned long stack; + int err; - if(io_setup(256, &ctx)){ + if(io_setup(256, &ctx)){ err = -errno; - printk("aio_thread failed to initialize context, err = %d\n", - errno); - return err; - } + printk("aio_thread failed to initialize context, err = %d\n", + errno); + return err; + } - err = run_helper_thread(aio_thread, NULL, - CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); - if(err < 0) - return err; + err = run_helper_thread(aio_thread, NULL, + CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); + if(err < 0) + return err; - aio_pid = err; + aio_pid = err; printk("Using 2.6 host AIO\n"); - return 0; + return 0; } static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, unsigned long long offset, struct aio_context *aio) { - struct aio_thread_reply reply; - int err; - - err = do_aio(ctx, type, io_fd, buf, len, offset, aio); - if(err){ - reply = ((struct aio_thread_reply) { .data = aio, - .err = err }); - err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); - if(err != sizeof(reply)) - printk("submit_aio_26 - write failed, " - "fd = %d, err = %d\n", aio->reply_fd, -err); - else err = 0; - } - - return err; + struct aio_thread_reply reply; + int err; + + err = do_aio(ctx, type, io_fd, buf, len, offset, aio); + if(err){ + reply = ((struct aio_thread_reply) { .data = aio, + .err = err }); + err = os_write_file(aio->reply_fd, &reply, sizeof(reply)); + if(err != sizeof(reply)) + printk("submit_aio_26 - write failed, " + "fd = %d, err = %d\n", aio->reply_fd, -err); + else err = 0; + } + + return err; } #else #define DEFAULT_24_AIO 1 static int init_aio_26(void) { - return -ENOSYS; + return -ENOSYS; } static int submit_aio_26(enum aio_type type, int io_fd, char *buf, int len, unsigned long long offset, struct aio_context *aio) { - return -ENOSYS; + return -ENOSYS; } #endif @@ -312,8 +310,8 @@ static int aio_24 = DEFAULT_24_AIO; static int __init set_aio_24(char *name, int *add) { - aio_24 = 1; - return 0; + aio_24 = 1; + return 0; } __uml_setup("aio=2.4", set_aio_24, @@ -330,27 +328,28 @@ __uml_setup("aio=2.4", set_aio_24, static int init_aio(void) { - int err; - - CHOOSE_MODE(({ if(!aio_24){ - printk("Disabling 2.6 AIO in tt mode\n"); - aio_24 = 1; - } }), (void) 0); - - if(!aio_24){ - err = init_aio_26(); - if(err && (errno == ENOSYS)){ - printk("2.6 AIO not supported on the host - " - "reverting to 2.4 AIO\n"); - aio_24 = 1; - } - else return err; - } - - if(aio_24) - return init_aio_24(); - - return 0; + int err; + + CHOOSE_MODE(({ + if(!aio_24){ + printk("Disabling 2.6 AIO in tt mode\n"); + aio_24 = 1; + } }), (void) 0); + + if(!aio_24){ + err = init_aio_26(); + if(err && (errno == ENOSYS)){ + printk("2.6 AIO not supported on the host - " + "reverting to 2.4 AIO\n"); + aio_24 = 1; + } + else return err; + } + + if(aio_24) + return init_aio_24(); + + return 0; } /* The reason for the __initcall/__uml_exitcall asymmetry is that init_aio @@ -363,8 +362,8 @@ __initcall(init_aio); static void exit_aio(void) { - if(aio_pid != -1) - os_kill_process(aio_pid, 1); + if(aio_pid != -1) + os_kill_process(aio_pid, 1); } __uml_exitcall(exit_aio); @@ -372,30 +371,30 @@ __uml_exitcall(exit_aio); static int submit_aio_24(enum aio_type type, int io_fd, char *buf, int len, unsigned long long offset, struct aio_context *aio) { - struct aio_thread_req req = { .type = type, - .io_fd = io_fd, - .offset = offset, - .buf = buf, - .len = len, - .aio = aio, - }; - int err; - - err = os_write_file(aio_req_fd_w, &req, sizeof(req)); - if(err == sizeof(req)) - err = 0; - - return err; + struct aio_thread_req req = { .type = type, + .io_fd = io_fd, + .offset = offset, + .buf = buf, + .len = len, + .aio = aio, + }; + int err; + + err = os_write_file(aio_req_fd_w, &req, sizeof(req)); + if(err == sizeof(req)) + err = 0; + + return err; } int submit_aio(enum aio_type type, int io_fd, char *buf, int len, - unsigned long long offset, int reply_fd, - struct aio_context *aio) + unsigned long long offset, int reply_fd, + struct aio_context *aio) { - aio->reply_fd = reply_fd; - if(aio_24) - return submit_aio_24(type, io_fd, buf, len, offset, aio); - else { - return submit_aio_26(type, io_fd, buf, len, offset, aio); - } + aio->reply_fd = reply_fd; + if(aio_24) + return submit_aio_24(type, io_fd, buf, len, offset, aio); + else { + return submit_aio_26(type, io_fd, buf, len, offset, aio); + } } diff --git a/trunk/arch/um/os-Linux/umid.c b/trunk/arch/um/os-Linux/umid.c deleted file mode 100644 index ecf107ae5ac8..000000000000 --- a/trunk/arch/um/os-Linux/umid.c +++ /dev/null @@ -1,335 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "init.h" -#include "os.h" -#include "user.h" -#include "mode.h" - -#define UML_DIR "~/.uml/" - -#define UMID_LEN 64 - -/* Changed by set_umid, which is run early in boot */ -char umid[UMID_LEN] = { 0 }; - -/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ -static char *uml_dir = UML_DIR; - -static int __init make_uml_dir(void) -{ - char dir[512] = { '\0' }; - int len, err; - - if(*uml_dir == '~'){ - char *home = getenv("HOME"); - - err = -ENOENT; - if(home == NULL){ - printk("make_uml_dir : no value in environment for " - "$HOME\n"); - goto err; - } - strlcpy(dir, home, sizeof(dir)); - uml_dir++; - } - strlcat(dir, uml_dir, sizeof(dir)); - len = strlen(dir); - if (len > 0 && dir[len - 1] != '/') - strlcat(dir, "/", sizeof(dir)); - - err = -ENOMEM; - uml_dir = malloc(strlen(dir) + 1); - if (uml_dir == NULL) { - printf("make_uml_dir : malloc failed, errno = %d\n", errno); - goto err; - } - strcpy(uml_dir, dir); - - if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ - printf("Failed to mkdir '%s': %s\n", uml_dir, strerror(errno)); - err = -errno; - goto err_free; - } - return 0; - -err_free: - free(uml_dir); -err: - uml_dir = NULL; - return err; -} - -static int actually_do_remove(char *dir) -{ - DIR *directory; - struct dirent *ent; - int len; - char file[256]; - - directory = opendir(dir); - if(directory == NULL) - return -errno; - - while((ent = readdir(directory)) != NULL){ - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) - continue; - len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; - if(len > sizeof(file)) - return -E2BIG; - - sprintf(file, "%s/%s", dir, ent->d_name); - if(unlink(file) < 0) - return -errno; - } - if(rmdir(dir) < 0) - return -errno; - - return 0; -} - -/* This says that there isn't already a user of the specified directory even if - * there are errors during the checking. This is because if these errors - * happen, the directory is unusable by the pre-existing UML, so we might as - * well take it over. This could happen either by - * the existing UML somehow corrupting its umid directory - * something other than UML sticking stuff in the directory - * this boot racing with a shutdown of the other UML - * In any of these cases, the directory isn't useful for anything else. - */ - -static int not_dead_yet(char *dir) -{ - char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; - char pid[sizeof("nnnnn\0")], *end; - int dead, fd, p, n, err; - - n = snprintf(file, sizeof(file), "%s/pid", dir); - if(n >= sizeof(file)){ - printk("not_dead_yet - pid filename too long\n"); - err = -E2BIG; - goto out; - } - - dead = 0; - fd = open(file, O_RDONLY); - if(fd < 0){ - if(fd != -ENOENT){ - printk("not_dead_yet : couldn't open pid file '%s', " - "err = %d\n", file, -fd); - } - goto out; - } - - err = 0; - n = read(fd, pid, sizeof(pid)); - if(n <= 0){ - printk("not_dead_yet : couldn't read pid file '%s', " - "err = %d\n", file, -n); - goto out_close; - } - - p = strtoul(pid, &end, 0); - if(end == pid){ - printk("not_dead_yet : couldn't parse pid file '%s', " - "errno = %d\n", file, errno); - goto out_close; - } - - if((kill(p, 0) == 0) || (errno != ESRCH)) - return 1; - - err = actually_do_remove(dir); - if(err) - printk("not_dead_yet - actually_do_remove failed with " - "err = %d\n", err); - - return err; - - out_close: - close(fd); - out: - return 0; -} - -static void __init create_pid_file(void) -{ - char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; - char pid[sizeof("nnnnn\0")]; - int fd, n; - - if(umid_file_name("pid", file, sizeof(file))) - return; - - fd = open(file, O_RDWR | O_CREAT | O_EXCL, 0644); - if(fd < 0){ - printk("Open of machine pid file \"%s\" failed: %s\n", - file, strerror(-fd)); - return; - } - - snprintf(pid, sizeof(pid), "%d\n", getpid()); - n = write(fd, pid, strlen(pid)); - if(n != strlen(pid)) - printk("Write of pid file failed - err = %d\n", -n); - - close(fd); -} - -int __init set_umid(char *name) -{ - if(strlen(name) > UMID_LEN - 1) - return -E2BIG; - - strlcpy(umid, name, sizeof(umid)); - - return 0; -} - -static int umid_setup = 0; - -int __init make_umid(void) -{ - int fd, err; - char tmp[256]; - - if(umid_setup) - return 0; - - make_uml_dir(); - - if(*umid == '\0'){ - strlcpy(tmp, uml_dir, sizeof(tmp)); - strlcat(tmp, "XXXXXX", sizeof(tmp)); - fd = mkstemp(tmp); - if(fd < 0){ - printk("make_umid - mkstemp(%s) failed: %s\n", - tmp, strerror(errno)); - err = -errno; - goto err; - } - - close(fd); - - set_umid(&tmp[strlen(uml_dir)]); - - /* There's a nice tiny little race between this unlink and - * the mkdir below. It'd be nice if there were a mkstemp - * for directories. - */ - if(unlink(tmp)){ - err = -errno; - goto err; - } - } - - snprintf(tmp, sizeof(tmp), "%s%s", uml_dir, umid); - err = mkdir(tmp, 0777); - if(err < 0){ - err = -errno; - if(errno != EEXIST) - goto err; - - if(not_dead_yet(tmp) < 0) - goto err; - - err = mkdir(tmp, 0777); - } - if(err < 0){ - printk("Failed to create '%s' - err = %d\n", umid, err); - goto err_rmdir; - } - - umid_setup = 1; - - create_pid_file(); - - return 0; - - err_rmdir: - rmdir(tmp); - err: - return err; -} - -static int __init make_umid_init(void) -{ - make_umid(); - - return 0; -} - -__initcall(make_umid_init); - -int __init umid_file_name(char *name, char *buf, int len) -{ - int n, err; - - err = make_umid(); - if(err) - return err; - - n = snprintf(buf, len, "%s%s/%s", uml_dir, umid, name); - if(n >= len){ - printk("umid_file_name : buffer too short\n"); - return -E2BIG; - } - - return 0; -} - -char *get_umid(void) -{ - return umid; -} - -static int __init set_uml_dir(char *name, int *add) -{ - if(*name == '\0'){ - printf("uml_dir can't be an empty string\n"); - return 0; - } - - if(name[strlen(name) - 1] == '/'){ - uml_dir = name; - return 0; - } - - uml_dir = malloc(strlen(name) + 2); - if(uml_dir == NULL){ - printf("Failed to malloc uml_dir - error = %d\n", errno); - - /* Return 0 here because do_initcalls doesn't look at - * the return value. - */ - return 0; - } - sprintf(uml_dir, "%s/", name); - - return 0; -} - -__uml_setup("uml_dir=", set_uml_dir, -"uml_dir=\n" -" The location to place the pid and umid files.\n\n" -); - -static void remove_umid_dir(void) -{ - char dir[strlen(uml_dir) + UMID_LEN + 1], err; - - sprintf(dir, "%s%s", uml_dir, umid); - err = actually_do_remove(dir); - if(err) - printf("remove_umid_dir - actually_do_remove failed with " - "err = %d\n", err); -} - -__uml_exitcall(remove_umid_dir); diff --git a/trunk/arch/x86_64/Kconfig.debug b/trunk/arch/x86_64/Kconfig.debug index fcb06a50fdd2..e2c6e64a85ec 100644 --- a/trunk/arch/x86_64/Kconfig.debug +++ b/trunk/arch/x86_64/Kconfig.debug @@ -9,16 +9,6 @@ config INIT_DEBUG Fill __init and __initdata at the end of boot. This helps debugging illegal uses of __init and __initdata after initialization. -config DEBUG_RODATA - bool "Write protect kernel read-only data structures" - depends on DEBUG_KERNEL - help - Mark the kernel read-only data as write-protected in the pagetables, - in order to catch accidental (and incorrect) writes to such const data. - This option may have a slight performance impact because a portion - of the kernel code won't be covered by a 2MB TLB anymore. - If in doubt, say "N". - config IOMMU_DEBUG depends on GART_IOMMU && DEBUG_KERNEL bool "Enable IOMMU debugging" diff --git a/trunk/arch/x86_64/ia32/ia32entry.S b/trunk/arch/x86_64/ia32/ia32entry.S index df0773c9bdbe..e0eb0c712fe9 100644 --- a/trunk/arch/x86_64/ia32/ia32entry.S +++ b/trunk/arch/x86_64/ia32/ia32entry.S @@ -341,7 +341,7 @@ ENTRY(ia32_ptregs_common) jmp ia32_sysret /* misbalances the return cache */ CFI_ENDPROC - .section .rodata,"a" + .data .align 8 .globl ia32_sys_call_table ia32_sys_call_table: diff --git a/trunk/arch/x86_64/kernel/process.c b/trunk/arch/x86_64/kernel/process.c index 3060ed97b755..7519fc520eb3 100644 --- a/trunk/arch/x86_64/kernel/process.c +++ b/trunk/arch/x86_64/kernel/process.c @@ -157,7 +157,7 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait); DECLARE_PER_CPU(int, cpu_state); #include -/* We halt the CPU with physical CPU hotplug */ +/* We don't actually take CPU down, just spin without interrupts. */ static inline void play_dead(void) { idle_task_exit(); @@ -166,9 +166,8 @@ static inline void play_dead(void) /* Ack it */ __get_cpu_var(cpu_state) = CPU_DEAD; - local_irq_disable(); while (1) - halt(); + safe_halt(); } #else static inline void play_dead(void) diff --git a/trunk/arch/x86_64/kernel/syscall.c b/trunk/arch/x86_64/kernel/syscall.c index 7c176b3edde0..e263685f864c 100644 --- a/trunk/arch/x86_64/kernel/syscall.c +++ b/trunk/arch/x86_64/kernel/syscall.c @@ -19,7 +19,7 @@ typedef void (*sys_call_ptr_t)(void); extern void sys_ni_syscall(void); -const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { +sys_call_ptr_t sys_call_table[__NR_syscall_max+1] __cacheline_aligned = { /* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */ [0 ... __NR_syscall_max] = &sys_ni_syscall, #include diff --git a/trunk/arch/x86_64/mm/init.c b/trunk/arch/x86_64/mm/init.c index 1faae5fc1c01..c016dfe84784 100644 --- a/trunk/arch/x86_64/mm/init.c +++ b/trunk/arch/x86_64/mm/init.c @@ -498,29 +498,6 @@ void free_initmem(void) printk ("Freeing unused kernel memory: %luk freed\n", (__init_end - __init_begin) >> 10); } -#ifdef CONFIG_DEBUG_RODATA - -extern char __start_rodata, __end_rodata; -void mark_rodata_ro(void) -{ - unsigned long addr = (unsigned long)&__start_rodata; - - for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE) - change_page_attr_addr(addr, 1, PAGE_KERNEL_RO); - - printk ("Write protecting the kernel read-only data: %luk\n", - (&__end_rodata - &__start_rodata) >> 10); - - /* - * change_page_attr_addr() requires a global_flush_tlb() call after it. - * We do this after the printk so that if something went wrong in the - * change, the printk gets out at least to give a better debug hint - * of who is the culprit. - */ - global_flush_tlb(); -} -#endif - #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { diff --git a/trunk/arch/x86_64/mm/pageattr.c b/trunk/arch/x86_64/mm/pageattr.c index 35f1f1aab063..b90e8fe9eeb0 100644 --- a/trunk/arch/x86_64/mm/pageattr.c +++ b/trunk/arch/x86_64/mm/pageattr.c @@ -128,7 +128,6 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, pte_t *kpte; struct page *kpte_page; unsigned kpte_flags; - pgprot_t ref_prot2; kpte = lookup_address(address); if (!kpte) return 0; kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK); @@ -141,14 +140,10 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot, * split_large_page will take the reference for this change_page_attr * on the split page. */ - - struct page *split; - ref_prot2 = __pgprot(pgprot_val(pte_pgprot(*lookup_address(address))) & ~(1<<_PAGE_BIT_PSE)); - - split = split_large_page(address, prot, ref_prot2); + struct page *split = split_large_page(address, prot, ref_prot); if (!split) return -ENOMEM; - set_pte(kpte,mk_pte(split, ref_prot2)); + set_pte(kpte,mk_pte(split, ref_prot)); kpte_page = split; } get_page(kpte_page); diff --git a/trunk/block/Kconfig b/trunk/block/Kconfig index 377f6dd20e17..eb48edb80c1d 100644 --- a/trunk/block/Kconfig +++ b/trunk/block/Kconfig @@ -5,7 +5,7 @@ #for instance. config LBD bool "Support for Large Block Devices" - depends on X86 || (MIPS && 32BIT) || PPC32 || (S390 && !64BIT) || SUPERH || UML + depends on X86 || (MIPS && 32BIT) || PPC32 || ARCH_S390_31 || SUPERH || UML help Say Y here if you want to attach large (bigger than 2TB) discs to your machine, or if you want to have a raid or loopback device diff --git a/trunk/block/as-iosched.c b/trunk/block/as-iosched.c index 8da3cf66894c..43fa20495688 100644 --- a/trunk/block/as-iosched.c +++ b/trunk/block/as-iosched.c @@ -182,9 +182,6 @@ struct as_rq { static kmem_cache_t *arq_pool; -static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq); -static void as_antic_stop(struct as_data *ad); - /* * IO Context helper functions */ @@ -373,7 +370,7 @@ static struct as_rq *as_find_first_arq(struct as_data *ad, int data_dir) * existing request against the same sector), which can happen when using * direct IO, then return the alias. */ -static struct as_rq *__as_add_arq_rb(struct as_data *ad, struct as_rq *arq) +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; @@ -400,16 +397,6 @@ static struct as_rq *__as_add_arq_rb(struct as_data *ad, struct as_rq *arq) return NULL; } -static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq) -{ - struct as_rq *alias; - - while ((unlikely(alias = __as_add_arq_rb(ad, arq)))) { - as_move_to_dispatch(ad, alias); - as_antic_stop(ad); - } -} - static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq) { if (!ON_RB(&arq->rb_node)) { @@ -1146,6 +1133,23 @@ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) /* * take it off the sort and fifo list, add to dispatch queue */ + while (!list_empty(&rq->queuelist)) { + struct request *__rq = list_entry_rq(rq->queuelist.next); + struct as_rq *__arq = RQ_DATA(__rq); + + list_del(&__rq->queuelist); + + elv_dispatch_add_tail(ad->q, __rq); + + 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; + + ad->nr_dispatched++; + } + as_remove_queued_request(ad->q, rq); WARN_ON(arq->state != AS_RQ_QUEUED); @@ -1321,6 +1325,42 @@ static int as_dispatch_request(request_queue_t *q, int force) return 1; } +/* + * Add arq to a list behind alias + */ +static inline void +as_add_aliased_request(struct as_data *ad, struct as_rq *arq, + struct as_rq *alias) +{ + struct request *req = arq->request; + struct list_head *insert = alias->request->queuelist.prev; + + /* + * Transfer list of aliases + */ + while (!list_empty(&req->queuelist)) { + struct request *__rq = list_entry_rq(req->queuelist.next); + struct as_rq *__arq = RQ_DATA(__rq); + + list_move_tail(&__rq->queuelist, &alias->request->queuelist); + + WARN_ON(__arq->state != AS_RQ_QUEUED); + } + + /* + * Another request with the same start sector on the rbtree. + * Link this request to that sector. They are untangled in + * as_move_to_dispatch + */ + list_add(&arq->request->queuelist, insert); + + /* + * Don't want to have to handle merges. + */ + as_del_arq_hash(arq); + arq->request->flags |= REQ_NOMERGE; +} + /* * add arq to rbtree and fifo */ @@ -1328,6 +1368,7 @@ static void as_add_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_rq *alias; int data_dir; arq->state = AS_RQ_NEW; @@ -1346,17 +1387,33 @@ static void as_add_request(request_queue_t *q, struct request *rq) atomic_inc(&arq->io_context->aic->nr_queued); } - as_add_arq_rb(ad, arq); - if (rq_mergeable(arq->request)) - as_add_arq_hash(ad, arq); + alias = as_add_arq_rb(ad, arq); + if (!alias) { + /* + * 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]); - /* - * 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]); + if (rq_mergeable(arq->request)) + as_add_arq_hash(ad, arq); + as_update_arq(ad, arq); /* keep state machine up to date */ + + } else { + as_add_aliased_request(ad, arq, alias); + + /* + * 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); + } + } - as_update_arq(ad, arq); /* keep state machine up to date */ arq->state = AS_RQ_QUEUED; } @@ -1479,8 +1536,23 @@ static void as_merged_request(request_queue_t *q, struct request *req) * if the merge was a front merge, we need to reposition request */ if (rq_rb_key(req) != arq->rb_key) { + struct as_rq *alias, *next_arq = NULL; + + if (ad->next_arq[arq->is_sync] == arq) + next_arq = as_find_next_arq(ad, arq); + + /* + * Note! We should really be moving any old aliased requests + * off this request and try to insert them into the rbtree. We + * currently don't bother. Ditto the next function. + */ as_del_arq_rb(ad, arq); - as_add_arq_rb(ad, arq); + if ((alias = as_add_arq_rb(ad, arq))) { + list_del_init(&arq->fifo); + as_add_aliased_request(ad, arq, alias); + if (next_arq) + ad->next_arq[arq->is_sync] = next_arq; + } /* * Note! At this stage of this and the next function, our next * request may not be optimal - eg the request may have "grown" @@ -1507,8 +1579,18 @@ static void as_merged_requests(request_queue_t *q, struct request *req, as_add_arq_hash(ad, arq); if (rq_rb_key(req) != arq->rb_key) { + struct as_rq *alias, *next_arq = NULL; + + if (ad->next_arq[arq->is_sync] == arq) + next_arq = as_find_next_arq(ad, arq); + as_del_arq_rb(ad, arq); - as_add_arq_rb(ad, arq); + if ((alias = as_add_arq_rb(ad, arq))) { + list_del_init(&arq->fifo); + as_add_aliased_request(ad, arq, alias); + if (next_arq) + ad->next_arq[arq->is_sync] = next_arq; + } } /* @@ -1527,6 +1609,18 @@ static void as_merged_requests(request_queue_t *q, struct request *req, } } + /* + * Transfer list of aliases + */ + while (!list_empty(&next->queuelist)) { + struct request *__rq = list_entry_rq(next->queuelist.next); + struct as_rq *__arq = RQ_DATA(__rq); + + list_move_tail(&__rq->queuelist, &req->queuelist); + + WARN_ON(__arq->state != AS_RQ_QUEUED); + } + /* * kill knowledge of next, this one is a goner */ diff --git a/trunk/block/cfq-iosched.c b/trunk/block/cfq-iosched.c index 74fae2daf87e..ee0bb41694b0 100644 --- a/trunk/block/cfq-iosched.c +++ b/trunk/block/cfq-iosched.c @@ -25,15 +25,15 @@ /* * tunables */ -static const int cfq_quantum = 4; /* max queue in one round of service */ -static const int cfq_queued = 8; /* minimum rq allocate limit per-queue*/ -static const int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; -static const int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ -static const int cfq_back_penalty = 2; /* penalty of a backwards seek */ +static int cfq_quantum = 4; /* max queue in one round of service */ +static int cfq_queued = 8; /* minimum rq allocate limit per-queue*/ +static int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 }; +static int cfq_back_max = 16 * 1024; /* maximum backwards seek, in KiB */ +static int cfq_back_penalty = 2; /* penalty of a backwards seek */ -static const int cfq_slice_sync = HZ / 10; +static int cfq_slice_sync = HZ / 10; static int cfq_slice_async = HZ / 25; -static const int cfq_slice_async_rq = 2; +static int cfq_slice_async_rq = 2; static int cfq_slice_idle = HZ / 100; #define CFQ_IDLE_GRACE (HZ / 10) @@ -45,7 +45,7 @@ static int cfq_slice_idle = HZ / 100; /* * disable queueing at the driver/hardware level */ -static const int cfq_max_depth = 2; +static int cfq_max_depth = 2; /* * for the hash of cfqq inside the cfqd diff --git a/trunk/block/deadline-iosched.c b/trunk/block/deadline-iosched.c index 27e494b1bf97..9cbec09e8415 100644 --- a/trunk/block/deadline-iosched.c +++ b/trunk/block/deadline-iosched.c @@ -19,10 +19,10 @@ /* * See Documentation/block/deadline-iosched.txt */ -static const int read_expire = HZ / 2; /* max time before a read is submitted. */ -static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */ -static const int writes_starved = 2; /* max times reads can starve a write */ -static const int fifo_batch = 16; /* # of sequential requests treated as one +static int read_expire = HZ / 2; /* max time before a read is submitted. */ +static int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */ +static int writes_starved = 2; /* max times reads can starve a write */ +static int fifo_batch = 16; /* # of sequential requests treated as one by the above parameters. For throughput. */ static const int deadline_hash_shift = 5; diff --git a/trunk/block/elevator.c b/trunk/block/elevator.c index 39dcccc82ada..6c3fc8a10bf2 100644 --- a/trunk/block/elevator.c +++ b/trunk/block/elevator.c @@ -304,7 +304,15 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) rq->flags &= ~REQ_STARTED; - __elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE, 0); + /* + * if this is the flush, requeue the original instead and drop the flush + */ + if (rq->flags & REQ_BAR_FLUSH) { + clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); + rq = rq->end_io_data; + } + + __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); } static void elv_drain_elevator(request_queue_t *q) @@ -324,18 +332,7 @@ static void elv_drain_elevator(request_queue_t *q) void __elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { - struct list_head *pos; - unsigned ordseq; - - if (q->ordcolor) - rq->flags |= REQ_ORDERED_COLOR; - if (rq->flags & (REQ_SOFTBARRIER | REQ_HARDBARRIER)) { - /* - * toggle ordered color - */ - q->ordcolor ^= 1; - /* * barriers implicitly indicate back insertion */ @@ -396,30 +393,6 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, q->elevator->ops->elevator_add_req_fn(q, rq); break; - case ELEVATOR_INSERT_REQUEUE: - /* - * If ordered flush isn't in progress, we do front - * insertion; otherwise, requests should be requeued - * in ordseq order. - */ - rq->flags |= REQ_SOFTBARRIER; - - if (q->ordseq == 0) { - list_add(&rq->queuelist, &q->queue_head); - break; - } - - ordseq = blk_ordered_req_seq(rq); - - list_for_each(pos, &q->queue_head) { - struct request *pos_rq = list_entry_rq(pos); - if (ordseq <= blk_ordered_req_seq(pos_rq)) - break; - } - - list_add_tail(&rq->queuelist, pos); - break; - default: printk(KERN_ERR "%s: bad insertion point %d\n", __FUNCTION__, where); @@ -449,16 +422,25 @@ static inline struct request *__elv_next_request(request_queue_t *q) { struct request *rq; - while (1) { - while (!list_empty(&q->queue_head)) { - rq = list_entry_rq(q->queue_head.next); - if (blk_do_ordered(q, &rq)) - return rq; - } + if (unlikely(list_empty(&q->queue_head) && + !q->elevator->ops->elevator_dispatch_fn(q, 0))) + return NULL; + + rq = list_entry_rq(q->queue_head.next); + + /* + * if this is a barrier write and the device has to issue a + * flush sequence to support it, check how far we are + */ + if (blk_fs_request(rq) && blk_barrier_rq(rq)) { + BUG_ON(q->ordered == QUEUE_ORDERED_NONE); - if (!q->elevator->ops->elevator_dispatch_fn(q, 0)) - return NULL; + if (q->ordered == QUEUE_ORDERED_FLUSH && + !blk_barrier_preflush(rq)) + rq = blk_start_pre_flush(q, rq); } + + return rq; } struct request *elv_next_request(request_queue_t *q) @@ -516,7 +498,7 @@ struct request *elv_next_request(request_queue_t *q) blkdev_dequeue_request(rq); rq->flags |= REQ_QUIET; end_that_request_chunk(rq, 0, nr_bytes); - end_that_request_last(rq, 0); + end_that_request_last(rq); } else { printk(KERN_ERR "%s: bad return=%d\n", __FUNCTION__, ret); @@ -611,21 +593,7 @@ void elv_completed_request(request_queue_t *q, struct request *rq) * request is released from the driver, io must be done */ if (blk_account_rq(rq)) { - struct request *first_rq = list_entry_rq(q->queue_head.next); - q->in_flight--; - - /* - * Check if the queue is waiting for fs requests to be - * drained for flush sequence. - */ - if (q->ordseq && q->in_flight == 0 && - blk_ordered_cur_seq(q) == QUEUE_ORDSEQ_DRAIN && - blk_ordered_req_seq(first_rq) > QUEUE_ORDSEQ_DRAIN) { - blk_ordered_complete_seq(q, QUEUE_ORDSEQ_DRAIN, 0); - q->request_fn(q); - } - if (blk_sorted_rq(rq) && e->ops->elevator_completed_req_fn) e->ops->elevator_completed_req_fn(q, rq); } diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index 91d3b4828c49..d4beb9a89ee0 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -36,8 +36,6 @@ static void blk_unplug_work(void *data); static void blk_unplug_timeout(unsigned long data); static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io); -static void init_request_from_bio(struct request *req, struct bio *bio); -static int __make_request(request_queue_t *q, struct bio *bio); /* * For the allocated request tables @@ -290,8 +288,8 @@ static inline void rq_init(request_queue_t *q, struct request *rq) /** * blk_queue_ordered - does this queue support ordered writes - * @q: the request queue - * @ordered: one of QUEUE_ORDERED_* + * @q: the request queue + * @flag: see below * * Description: * For journalled file systems, doing ordered writes on a commit @@ -300,30 +298,28 @@ static inline void rq_init(request_queue_t *q, struct request *rq) * feature should call this function and indicate so. * **/ -int blk_queue_ordered(request_queue_t *q, unsigned ordered, - prepare_flush_fn *prepare_flush_fn) -{ - if (ordered & (QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH) && - prepare_flush_fn == NULL) { - printk(KERN_ERR "blk_queue_ordered: prepare_flush_fn required\n"); - return -EINVAL; - } - - if (ordered != QUEUE_ORDERED_NONE && - ordered != QUEUE_ORDERED_DRAIN && - ordered != QUEUE_ORDERED_DRAIN_FLUSH && - ordered != QUEUE_ORDERED_DRAIN_FUA && - ordered != QUEUE_ORDERED_TAG && - ordered != QUEUE_ORDERED_TAG_FLUSH && - ordered != QUEUE_ORDERED_TAG_FUA) { - printk(KERN_ERR "blk_queue_ordered: bad value %d\n", ordered); - return -EINVAL; +void blk_queue_ordered(request_queue_t *q, int flag) +{ + switch (flag) { + case QUEUE_ORDERED_NONE: + if (q->flush_rq) + kmem_cache_free(request_cachep, q->flush_rq); + q->flush_rq = NULL; + q->ordered = flag; + break; + case QUEUE_ORDERED_TAG: + q->ordered = flag; + break; + case QUEUE_ORDERED_FLUSH: + q->ordered = flag; + if (!q->flush_rq) + q->flush_rq = kmem_cache_alloc(request_cachep, + GFP_KERNEL); + break; + default: + printk("blk_queue_ordered: bad value %d\n", flag); + break; } - - q->next_ordered = ordered; - q->prepare_flush_fn = prepare_flush_fn; - - return 0; } EXPORT_SYMBOL(blk_queue_ordered); @@ -348,266 +344,168 @@ EXPORT_SYMBOL(blk_queue_issue_flush_fn); /* * Cache flushing for ordered writes handling */ -inline unsigned blk_ordered_cur_seq(request_queue_t *q) -{ - if (!q->ordseq) - return 0; - return 1 << ffz(q->ordseq); -} - -unsigned blk_ordered_req_seq(struct request *rq) +static void blk_pre_flush_end_io(struct request *flush_rq) { + struct request *rq = flush_rq->end_io_data; request_queue_t *q = rq->q; - BUG_ON(q->ordseq == 0); + elv_completed_request(q, flush_rq); - if (rq == &q->pre_flush_rq) - return QUEUE_ORDSEQ_PREFLUSH; - if (rq == &q->bar_rq) - return QUEUE_ORDSEQ_BAR; - if (rq == &q->post_flush_rq) - return QUEUE_ORDSEQ_POSTFLUSH; + rq->flags |= REQ_BAR_PREFLUSH; - if ((rq->flags & REQ_ORDERED_COLOR) == - (q->orig_bar_rq->flags & REQ_ORDERED_COLOR)) - return QUEUE_ORDSEQ_DRAIN; - else - return QUEUE_ORDSEQ_DONE; + if (!flush_rq->errors) + elv_requeue_request(q, rq); + else { + q->end_flush_fn(q, flush_rq); + clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); + q->request_fn(q); + } } -void blk_ordered_complete_seq(request_queue_t *q, unsigned seq, int error) +static void blk_post_flush_end_io(struct request *flush_rq) { - struct request *rq; - int uptodate; - - if (error && !q->orderr) - q->orderr = error; - - BUG_ON(q->ordseq & seq); - q->ordseq |= seq; - - if (blk_ordered_cur_seq(q) != QUEUE_ORDSEQ_DONE) - return; - - /* - * Okay, sequence complete. - */ - rq = q->orig_bar_rq; - uptodate = q->orderr ? q->orderr : 1; + struct request *rq = flush_rq->end_io_data; + request_queue_t *q = rq->q; - q->ordseq = 0; + elv_completed_request(q, flush_rq); - end_that_request_first(rq, uptodate, rq->hard_nr_sectors); - end_that_request_last(rq, uptodate); -} + rq->flags |= REQ_BAR_POSTFLUSH; -static void pre_flush_end_io(struct request *rq, int error) -{ - elv_completed_request(rq->q, rq); - blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_PREFLUSH, error); -} - -static void bar_end_io(struct request *rq, int error) -{ - elv_completed_request(rq->q, rq); - blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_BAR, error); -} - -static void post_flush_end_io(struct request *rq, int error) -{ - elv_completed_request(rq->q, rq); - blk_ordered_complete_seq(rq->q, QUEUE_ORDSEQ_POSTFLUSH, error); + q->end_flush_fn(q, flush_rq); + clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); + q->request_fn(q); } -static void queue_flush(request_queue_t *q, unsigned which) +struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq) { - struct request *rq; - rq_end_io_fn *end_io; - - if (which == QUEUE_ORDERED_PREFLUSH) { - rq = &q->pre_flush_rq; - end_io = pre_flush_end_io; - } else { - rq = &q->post_flush_rq; - end_io = post_flush_end_io; - } + struct request *flush_rq = q->flush_rq; - rq_init(q, rq); - rq->flags = REQ_HARDBARRIER; - rq->elevator_private = NULL; - rq->rq_disk = q->bar_rq.rq_disk; - rq->rl = NULL; - rq->end_io = end_io; - q->prepare_flush_fn(q, rq); + BUG_ON(!blk_barrier_rq(rq)); - __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); -} + if (test_and_set_bit(QUEUE_FLAG_FLUSH, &q->queue_flags)) + return NULL; -static inline struct request *start_ordered(request_queue_t *q, - struct request *rq) -{ - q->bi_size = 0; - q->orderr = 0; - q->ordered = q->next_ordered; - q->ordseq |= QUEUE_ORDSEQ_STARTED; + rq_init(q, flush_rq); + flush_rq->elevator_private = NULL; + flush_rq->flags = REQ_BAR_FLUSH; + flush_rq->rq_disk = rq->rq_disk; + flush_rq->rl = NULL; /* - * Prep proxy barrier request. + * prepare_flush returns 0 if no flush is needed, just mark both + * pre and post flush as done in that case */ - blkdev_dequeue_request(rq); - q->orig_bar_rq = rq; - rq = &q->bar_rq; - rq_init(q, rq); - rq->flags = bio_data_dir(q->orig_bar_rq->bio); - rq->flags |= q->ordered & QUEUE_ORDERED_FUA ? REQ_FUA : 0; - rq->elevator_private = NULL; - rq->rl = NULL; - init_request_from_bio(rq, q->orig_bar_rq->bio); - rq->end_io = bar_end_io; + if (!q->prepare_flush_fn(q, flush_rq)) { + rq->flags |= REQ_BAR_PREFLUSH | REQ_BAR_POSTFLUSH; + clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags); + return rq; + } /* - * Queue ordered sequence. As we stack them at the head, we - * need to queue in reverse order. Note that we rely on that - * no fs request uses ELEVATOR_INSERT_FRONT and thus no fs - * request gets inbetween ordered sequence. + * some drivers dequeue requests right away, some only after io + * completion. make sure the request is dequeued. */ - if (q->ordered & QUEUE_ORDERED_POSTFLUSH) - queue_flush(q, QUEUE_ORDERED_POSTFLUSH); - else - q->ordseq |= QUEUE_ORDSEQ_POSTFLUSH; - - __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); - - if (q->ordered & QUEUE_ORDERED_PREFLUSH) { - queue_flush(q, QUEUE_ORDERED_PREFLUSH); - rq = &q->pre_flush_rq; - } else - q->ordseq |= QUEUE_ORDSEQ_PREFLUSH; + if (!list_empty(&rq->queuelist)) + blkdev_dequeue_request(rq); - if ((q->ordered & QUEUE_ORDERED_TAG) || q->in_flight == 0) - q->ordseq |= QUEUE_ORDSEQ_DRAIN; - else - rq = NULL; + flush_rq->end_io_data = rq; + flush_rq->end_io = blk_pre_flush_end_io; - return rq; + __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0); + return flush_rq; } -int blk_do_ordered(request_queue_t *q, struct request **rqp) +static void blk_start_post_flush(request_queue_t *q, struct request *rq) { - struct request *rq = *rqp, *allowed_rq; - int is_barrier = blk_fs_request(rq) && blk_barrier_rq(rq); + struct request *flush_rq = q->flush_rq; - if (!q->ordseq) { - if (!is_barrier) - return 1; + BUG_ON(!blk_barrier_rq(rq)); - if (q->next_ordered != QUEUE_ORDERED_NONE) { - *rqp = start_ordered(q, rq); - return 1; - } else { - /* - * This can happen when the queue switches to - * ORDERED_NONE while this request is on it. - */ - blkdev_dequeue_request(rq); - end_that_request_first(rq, -EOPNOTSUPP, - rq->hard_nr_sectors); - end_that_request_last(rq, -EOPNOTSUPP); - *rqp = NULL; - return 0; - } - } + rq_init(q, flush_rq); + flush_rq->elevator_private = NULL; + flush_rq->flags = REQ_BAR_FLUSH; + flush_rq->rq_disk = rq->rq_disk; + flush_rq->rl = NULL; - if (q->ordered & QUEUE_ORDERED_TAG) { - if (is_barrier && rq != &q->bar_rq) - *rqp = NULL; - return 1; - } + if (q->prepare_flush_fn(q, flush_rq)) { + flush_rq->end_io_data = rq; + flush_rq->end_io = blk_post_flush_end_io; - switch (blk_ordered_cur_seq(q)) { - case QUEUE_ORDSEQ_PREFLUSH: - allowed_rq = &q->pre_flush_rq; - break; - case QUEUE_ORDSEQ_BAR: - allowed_rq = &q->bar_rq; - break; - case QUEUE_ORDSEQ_POSTFLUSH: - allowed_rq = &q->post_flush_rq; - break; - default: - allowed_rq = NULL; - break; + __elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0); + q->request_fn(q); } - - if (rq != allowed_rq && - (blk_fs_request(rq) || rq == &q->pre_flush_rq || - rq == &q->post_flush_rq)) - *rqp = NULL; - - return 1; } -static int flush_dry_bio_endio(struct bio *bio, unsigned int bytes, int error) +static inline int blk_check_end_barrier(request_queue_t *q, struct request *rq, + int sectors) { - request_queue_t *q = bio->bi_private; - struct bio_vec *bvec; - int i; - - /* - * This is dry run, restore bio_sector and size. We'll finish - * this request again with the original bi_end_io after an - * error occurs or post flush is complete. - */ - q->bi_size += bytes; + if (sectors > rq->nr_sectors) + sectors = rq->nr_sectors; - if (bio->bi_size) - return 1; - - /* Rewind bvec's */ - bio->bi_idx = 0; - bio_for_each_segment(bvec, bio, i) { - bvec->bv_len += bvec->bv_offset; - bvec->bv_offset = 0; - } - - /* Reset bio */ - set_bit(BIO_UPTODATE, &bio->bi_flags); - bio->bi_size = q->bi_size; - bio->bi_sector -= (q->bi_size >> 9); - q->bi_size = 0; - - return 0; + rq->nr_sectors -= sectors; + return rq->nr_sectors; } -static inline int ordered_bio_endio(struct request *rq, struct bio *bio, - unsigned int nbytes, int error) +static int __blk_complete_barrier_rq(request_queue_t *q, struct request *rq, + int sectors, int queue_locked) { - request_queue_t *q = rq->q; - bio_end_io_t *endio; - void *private; - - if (&q->bar_rq != rq) + if (q->ordered != QUEUE_ORDERED_FLUSH) + return 0; + if (!blk_fs_request(rq) || !blk_barrier_rq(rq)) + return 0; + if (blk_barrier_postflush(rq)) return 0; - /* - * Okay, this is the barrier request in progress, dry finish it. - */ - if (error && !q->orderr) - q->orderr = error; + if (!blk_check_end_barrier(q, rq, sectors)) { + unsigned long flags = 0; - endio = bio->bi_end_io; - private = bio->bi_private; - bio->bi_end_io = flush_dry_bio_endio; - bio->bi_private = q; + if (!queue_locked) + spin_lock_irqsave(q->queue_lock, flags); - bio_endio(bio, nbytes, error); + blk_start_post_flush(q, rq); - bio->bi_end_io = endio; - bio->bi_private = private; + if (!queue_locked) + spin_unlock_irqrestore(q->queue_lock, flags); + } return 1; } +/** + * blk_complete_barrier_rq - complete possible barrier request + * @q: the request queue for the device + * @rq: the request + * @sectors: number of sectors to complete + * + * Description: + * Used in driver end_io handling to determine whether to postpone + * completion of a barrier request until a post flush has been done. This + * is the unlocked variant, used if the caller doesn't already hold the + * queue lock. + **/ +int blk_complete_barrier_rq(request_queue_t *q, struct request *rq, int sectors) +{ + return __blk_complete_barrier_rq(q, rq, sectors, 0); +} +EXPORT_SYMBOL(blk_complete_barrier_rq); + +/** + * blk_complete_barrier_rq_locked - complete possible barrier request + * @q: the request queue for the device + * @rq: the request + * @sectors: number of sectors to complete + * + * Description: + * See blk_complete_barrier_rq(). This variant must be used if the caller + * holds the queue lock. + **/ +int blk_complete_barrier_rq_locked(request_queue_t *q, struct request *rq, + int sectors) +{ + return __blk_complete_barrier_rq(q, rq, sectors, 1); +} +EXPORT_SYMBOL(blk_complete_barrier_rq_locked); + /** * blk_queue_bounce_limit - set bounce buffer limit for queue * @q: the request queue for the device @@ -1141,13 +1039,12 @@ void blk_queue_invalidate_tags(request_queue_t *q) EXPORT_SYMBOL(blk_queue_invalidate_tags); -static const char * const rq_flags[] = { +static char *rq_flags[] = { "REQ_RW", "REQ_FAILFAST", "REQ_SORTED", "REQ_SOFTBARRIER", "REQ_HARDBARRIER", - "REQ_FUA", "REQ_CMD", "REQ_NOMERGE", "REQ_STARTED", @@ -1167,7 +1064,6 @@ static const char * const rq_flags[] = { "REQ_PM_SUSPEND", "REQ_PM_RESUME", "REQ_PM_SHUTDOWN", - "REQ_ORDERED_COLOR", }; void blk_dump_rq_flags(struct request *rq, char *msg) @@ -1745,6 +1641,8 @@ void blk_cleanup_queue(request_queue_t * q) if (q->queue_tags) __blk_queue_free_tags(q); + blk_queue_ordered(q, QUEUE_ORDERED_NONE); + kmem_cache_free(requestq_cachep, q); } @@ -1769,6 +1667,8 @@ static int blk_init_free_list(request_queue_t *q) return 0; } +static int __make_request(request_queue_t *, struct bio *); + request_queue_t *blk_alloc_queue(gfp_t gfp_mask) { return blk_alloc_queue_node(gfp_mask, -1); @@ -2008,40 +1908,40 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, { struct request *rq = NULL; struct request_list *rl = &q->rq; - struct io_context *ioc = NULL; - int may_queue, priv; - - may_queue = elv_may_queue(q, rw, bio); - if (may_queue == ELV_MQUEUE_NO) - goto rq_starved; + struct io_context *ioc = current_io_context(GFP_ATOMIC); + int priv; - if (rl->count[rw]+1 >= queue_congestion_on_threshold(q)) { - if (rl->count[rw]+1 >= q->nr_requests) { - ioc = current_io_context(GFP_ATOMIC); - /* - * 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(q, ioc); - blk_set_queue_full(q, rw); - } else { - if (may_queue != ELV_MQUEUE_MUST - && !ioc_batching(q, ioc)) { - /* - * The queue is full and the allocating - * process is not a "batcher", and not - * exempted by the IO scheduler - */ - goto out; - } - } + 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(q, ioc); + blk_set_queue_full(q, rw); } - set_queue_congested(q, rw); } + switch (elv_may_queue(q, rw, bio)) { + case ELV_MQUEUE_NO: + goto rq_starved; + case ELV_MQUEUE_MAY: + break; + case ELV_MQUEUE_MUST: + goto get_rq; + } + + if (blk_queue_full(q, rw) && !ioc_batching(q, ioc)) { + /* + * The queue is full and the allocating process is not a + * "batcher", and not exempted by the IO scheduler + */ + goto out; + } + +get_rq: /* * Only allow batching queuers to allocate up to 50% over the defined * limit of requests, otherwise we could have thousands of requests @@ -2052,6 +1952,8 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, rl->count[rw]++; rl->starved[rw] = 0; + if (rl->count[rw] >= queue_congestion_on_threshold(q)) + set_queue_congested(q, rw); priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); if (priv) @@ -2060,7 +1962,7 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, spin_unlock_irq(q->queue_lock); rq = blk_alloc_request(q, rw, bio, priv, gfp_mask); - if (unlikely(!rq)) { + if (!rq) { /* * Allocation failed presumably due to memory. Undo anything * we might have messed up. @@ -2085,12 +1987,6 @@ static struct request *get_request(request_queue_t *q, int rw, struct bio *bio, goto out; } - /* - * ioc may be NULL here, and ioc_batching will be false. That's - * OK, if the queue is under the request limit then requests need - * not count toward the nr_batch_requests limit. There will always - * be some limit enforced by BLK_BATCH_TIME. - */ if (ioc_batching(q, ioc)) ioc->nr_batch_requests--; @@ -2417,7 +2313,7 @@ EXPORT_SYMBOL(blk_rq_map_kern); */ void blk_execute_rq_nowait(request_queue_t *q, struct gendisk *bd_disk, struct request *rq, int at_head, - rq_end_io_fn *done) + void (*done)(struct request *)) { int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; @@ -2621,7 +2517,7 @@ EXPORT_SYMBOL(blk_put_request); * blk_end_sync_rq - executes a completion event on a request * @rq: request to complete */ -void blk_end_sync_rq(struct request *rq, int error) +void blk_end_sync_rq(struct request *rq) { struct completion *waiting = rq->waiting; @@ -2759,36 +2655,6 @@ void blk_attempt_remerge(request_queue_t *q, struct request *rq) EXPORT_SYMBOL(blk_attempt_remerge); -static void init_request_from_bio(struct request *req, struct bio *bio) -{ - req->flags |= REQ_CMD; - - /* - * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) - */ - if (bio_rw_ahead(bio) || bio_failfast(bio)) - req->flags |= REQ_FAILFAST; - - /* - * REQ_BARRIER implies no merging, but lets make it explicit - */ - if (unlikely(bio_barrier(bio))) - req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); - - req->errors = 0; - req->hard_sector = req->sector = bio->bi_sector; - req->hard_nr_sectors = req->nr_sectors = bio_sectors(bio); - req->current_nr_sectors = req->hard_cur_sectors = bio_cur_sectors(bio); - req->nr_phys_segments = bio_phys_segments(req->q, bio); - req->nr_hw_segments = bio_hw_segments(req->q, bio); - req->buffer = bio_data(bio); /* see ->buffer comment above */ - req->waiting = NULL; - req->bio = req->biotail = bio; - req->ioprio = bio_prio(bio); - req->rq_disk = bio->bi_bdev->bd_disk; - req->start_time = jiffies; -} - static int __make_request(request_queue_t *q, struct bio *bio) { struct request *req; @@ -2814,7 +2680,7 @@ static int __make_request(request_queue_t *q, struct bio *bio) spin_lock_prefetch(q->queue_lock); barrier = bio_barrier(bio); - if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) { + if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) { err = -EOPNOTSUPP; goto end_io; } @@ -2884,7 +2750,33 @@ static int __make_request(request_queue_t *q, struct bio *bio) * We don't worry about that case for efficiency. It won't happen * often, and the elevators are able to handle it. */ - init_request_from_bio(req, bio); + + req->flags |= REQ_CMD; + + /* + * inherit FAILFAST from bio (for read-ahead, and explicit FAILFAST) + */ + if (bio_rw_ahead(bio) || bio_failfast(bio)) + req->flags |= REQ_FAILFAST; + + /* + * REQ_BARRIER implies no merging, but lets make it explicit + */ + if (unlikely(barrier)) + req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE); + + req->errors = 0; + req->hard_sector = req->sector = sector; + req->hard_nr_sectors = req->nr_sectors = nr_sectors; + req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors; + req->nr_phys_segments = bio_phys_segments(q, bio); + req->nr_hw_segments = bio_hw_segments(q, bio); + req->buffer = bio_data(bio); /* see ->buffer comment above */ + req->waiting = NULL; + req->bio = req->biotail = bio; + req->ioprio = prio; + req->rq_disk = bio->bi_bdev->bd_disk; + req->start_time = jiffies; spin_lock_irq(q->queue_lock); if (elv_queue_empty(q)) @@ -3175,8 +3067,7 @@ static int __end_that_request_first(struct request *req, int uptodate, if (nr_bytes >= bio->bi_size) { req->bio = bio->bi_next; nbytes = bio->bi_size; - if (!ordered_bio_endio(req, bio, nbytes, error)) - bio_endio(bio, nbytes, error); + bio_endio(bio, nbytes, error); next_idx = 0; bio_nbytes = 0; } else { @@ -3231,8 +3122,7 @@ static int __end_that_request_first(struct request *req, int uptodate, * if the request wasn't completed, update state */ if (bio_nbytes) { - if (!ordered_bio_endio(req, bio, bio_nbytes, error)) - bio_endio(bio, bio_nbytes, error); + bio_endio(bio, bio_nbytes, error); bio->bi_idx += next_idx; bio_iovec(bio)->bv_offset += nr_bytes; bio_iovec(bio)->bv_len -= nr_bytes; @@ -3289,17 +3179,9 @@ EXPORT_SYMBOL(end_that_request_chunk); /* * queue lock must be held */ -void end_that_request_last(struct request *req, int uptodate) +void end_that_request_last(struct request *req) { struct gendisk *disk = req->rq_disk; - int error; - - /* - * extend uptodate bool to allow < 0 value to be direct io error - */ - error = 0; - if (end_io_error(uptodate)) - error = !uptodate ? -EIO : uptodate; if (unlikely(laptop_mode) && blk_fs_request(req)) laptop_io_completion(); @@ -3314,7 +3196,7 @@ void end_that_request_last(struct request *req, int uptodate) disk->in_flight--; } if (req->end_io) - req->end_io(req, error); + req->end_io(req); else __blk_put_request(req->q, req); } @@ -3326,7 +3208,7 @@ void end_request(struct request *req, int uptodate) if (!end_that_request_first(req, uptodate, req->hard_cur_sectors)) { add_disk_randomness(req->rq_disk); blkdev_dequeue_request(req); - end_that_request_last(req, uptodate); + end_that_request_last(req); } } diff --git a/trunk/block/scsi_ioctl.c b/trunk/block/scsi_ioctl.c index c2ac36dfe4f3..1d8852f7bbff 100644 --- a/trunk/block/scsi_ioctl.c +++ b/trunk/block/scsi_ioctl.c @@ -46,7 +46,7 @@ EXPORT_SYMBOL(scsi_command_size); static int sg_get_version(int __user *p) { - static const int sg_version_num = 30527; + static int sg_version_num = 30527; return put_user(sg_version_num, p); } diff --git a/trunk/crypto/Kconfig b/trunk/crypto/Kconfig index 52e1d4108a99..89299f4ffe12 100644 --- a/trunk/crypto/Kconfig +++ b/trunk/crypto/Kconfig @@ -40,11 +40,10 @@ config CRYPTO_SHA1 help SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). -config CRYPTO_SHA1_S390 - tristate "SHA1 digest algorithm (s390)" - depends on CRYPTO && S390 +config CRYPTO_SHA1_Z990 + tristate "SHA1 digest algorithm for IBM zSeries z990" + depends on CRYPTO && ARCH_S390 help - This is the s390 hardware accelerated implementation of the SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). config CRYPTO_SHA256 @@ -56,16 +55,6 @@ config CRYPTO_SHA256 This version of SHA implements a 256 bit hash with 128 bits of security against collision attacks. -config CRYPTO_SHA256_S390 - tristate "SHA256 digest algorithm (s390)" - depends on CRYPTO && S390 - help - This is the s390 hardware accelerated implementation of the - SHA256 secure hash standard (DFIPS 180-2). - - This version of SHA implements a 256 bit hash with 128 bits of - security against collision attacks. - config CRYPTO_SHA512 tristate "SHA384 and SHA512 digest algorithms" depends on CRYPTO @@ -109,9 +98,9 @@ config CRYPTO_DES help DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). -config CRYPTO_DES_S390 - tristate "DES and Triple DES cipher algorithms (s390)" - depends on CRYPTO && S390 +config CRYPTO_DES_Z990 + tristate "DES and Triple DES cipher algorithms for IBM zSeries z990" + depends on CRYPTO && ARCH_S390 help DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). @@ -215,26 +204,6 @@ config CRYPTO_AES_X86_64 See for more information. -config CRYPTO_AES_S390 - tristate "AES cipher algorithms (s390)" - depends on CRYPTO && S390 - help - This is the s390 hardware accelerated implementation of the - AES cipher algorithms (FIPS-197). AES uses the Rijndael - algorithm. - - Rijndael appears to be consistently a very good performer in - both hardware and software across a wide range of computing - environments regardless of its use in feedback or non-feedback - modes. Its key setup time is excellent, and its key agility is - good. Rijndael's very low memory requirements make it very well - suited for restricted-space environments, in which it also - demonstrates excellent performance. Rijndael's operations are - among the easiest to defend against power and timing attacks. - - On s390 the System z9-109 currently only supports the key size - of 128 bit. - config CRYPTO_CAST5 tristate "CAST5 (CAST-128) cipher algorithm" depends on CRYPTO diff --git a/trunk/crypto/tcrypt.c b/trunk/crypto/tcrypt.c index 49e344f00806..53f4ee804bdb 100644 --- a/trunk/crypto/tcrypt.c +++ b/trunk/crypto/tcrypt.c @@ -805,8 +805,6 @@ static void do_test(void) //AES test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS); test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS); - test_cipher ("aes", MODE_CBC, ENCRYPT, aes_cbc_enc_tv_template, AES_CBC_ENC_TEST_VECTORS); - test_cipher ("aes", MODE_CBC, DECRYPT, aes_cbc_dec_tv_template, AES_CBC_DEC_TEST_VECTORS); //CAST5 test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS); @@ -912,8 +910,6 @@ static void do_test(void) case 10: test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS); test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS); - test_cipher ("aes", MODE_CBC, ENCRYPT, aes_cbc_enc_tv_template, AES_CBC_ENC_TEST_VECTORS); - test_cipher ("aes", MODE_CBC, DECRYPT, aes_cbc_dec_tv_template, AES_CBC_DEC_TEST_VECTORS); break; case 11: diff --git a/trunk/crypto/tcrypt.h b/trunk/crypto/tcrypt.h index 733d07ed75e9..522ffd4b6f43 100644 --- a/trunk/crypto/tcrypt.h +++ b/trunk/crypto/tcrypt.h @@ -1836,8 +1836,6 @@ static struct cipher_testvec cast6_dec_tv_template[] = { */ #define AES_ENC_TEST_VECTORS 3 #define AES_DEC_TEST_VECTORS 3 -#define AES_CBC_ENC_TEST_VECTORS 2 -#define AES_CBC_DEC_TEST_VECTORS 2 static struct cipher_testvec aes_enc_tv_template[] = { { /* From FIPS-197 */ @@ -1913,68 +1911,6 @@ static struct cipher_testvec aes_dec_tv_template[] = { }, }; -static struct cipher_testvec aes_cbc_enc_tv_template[] = { - { /* From RFC 3602 */ - .key = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b, - 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 }, - .klen = 16, - .iv = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30, - 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 }, - .input = { "Single block msg" }, - .ilen = 16, - .result = { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8, - 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a }, - .rlen = 16, - }, { - .key = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, - 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a }, - .klen = 16, - .iv = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, - 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 }, - .input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - .ilen = 32, - .result = { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a, - 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a, - 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9, - 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 }, - .rlen = 32, - }, -}; - -static struct cipher_testvec aes_cbc_dec_tv_template[] = { - { /* From RFC 3602 */ - .key = { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b, - 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 }, - .klen = 16, - .iv = { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30, - 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 }, - .input = { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8, - 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a }, - .ilen = 16, - .result = { "Single block msg" }, - .rlen = 16, - }, { - .key = { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, - 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a }, - .klen = 16, - .iv = { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, - 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 }, - .input = { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a, - 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a, - 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9, - 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 }, - .ilen = 32, - .result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - .rlen = 32, - }, -}; - /* Cast5 test vectors from RFC 2144 */ #define CAST5_ENC_TEST_VECTORS 3 #define CAST5_DEC_TEST_VECTORS 3 diff --git a/trunk/drivers/base/memory.c b/trunk/drivers/base/memory.c index 58801d718cc2..7e1d077874df 100644 --- a/trunk/drivers/base/memory.c +++ b/trunk/drivers/base/memory.c @@ -49,12 +49,12 @@ static struct kset_uevent_ops memory_uevent_ops = { static struct notifier_block *memory_chain; -int register_memory_notifier(struct notifier_block *nb) +static int register_memory_notifier(struct notifier_block *nb) { return notifier_chain_register(&memory_chain, nb); } -void unregister_memory_notifier(struct notifier_block *nb) +static void unregister_memory_notifier(struct notifier_block *nb) { notifier_chain_unregister(&memory_chain, nb); } @@ -62,7 +62,8 @@ void unregister_memory_notifier(struct notifier_block *nb) /* * register_memory - Setup a sysfs device for a memory block */ -int register_memory(struct memory_block *memory, struct mem_section *section, +static int +register_memory(struct memory_block *memory, struct mem_section *section, struct node *root) { int error; diff --git a/trunk/drivers/block/DAC960.c b/trunk/drivers/block/DAC960.c index 21097a39a057..70eaa5c7ac08 100644 --- a/trunk/drivers/block/DAC960.c +++ b/trunk/drivers/block/DAC960.c @@ -3471,7 +3471,7 @@ static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command, if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) { - end_that_request_last(Request, UpToDate); + end_that_request_last(Request); if (Command->Completion) { complete(Command->Completion); diff --git a/trunk/drivers/block/Kconfig b/trunk/drivers/block/Kconfig index 139cbba76180..c4b9d2adfc08 100644 --- a/trunk/drivers/block/Kconfig +++ b/trunk/drivers/block/Kconfig @@ -117,7 +117,7 @@ config BLK_DEV_XD config PARIDE tristate "Parallel port IDE device support" - depends on PARPORT_PC + depends on PARPORT ---help--- There are many external CD-ROM and disk devices that connect through your computer's parallel port. Most of them are actually IDE devices diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index d2815b7a9150..c3441b3f086e 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -2310,7 +2310,7 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, printk("Done with %p\n", cmd->rq); #endif /* CCISS_DEBUG */ - end_that_request_last(cmd->rq, status ? 1 : -EIO); + end_that_request_last(cmd->rq); cmd_free(h,cmd,1); } diff --git a/trunk/drivers/block/cpqarray.c b/trunk/drivers/block/cpqarray.c index 9bddb6874873..cf1822a6361c 100644 --- a/trunk/drivers/block/cpqarray.c +++ b/trunk/drivers/block/cpqarray.c @@ -1036,7 +1036,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout) complete_buffers(cmd->rq->bio, ok); DBGPX(printk("Done with %p\n", cmd->rq);); - end_that_request_last(cmd->rq, ok ? 1 : -EIO); + end_that_request_last(cmd->rq); } /* diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index a5b857c5c4b8..f7e765a1d313 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -2301,7 +2301,7 @@ static void floppy_end_request(struct request *req, int uptodate) add_disk_randomness(req->rq_disk); floppy_off((long)req->rq_disk->private_data); blkdev_dequeue_request(req); - end_that_request_last(req, uptodate); + end_that_request_last(req); /* We're done with the request */ current_req = NULL; diff --git a/trunk/drivers/block/nbd.c b/trunk/drivers/block/nbd.c index 33d6f237b2ed..9e268ddedfbd 100644 --- a/trunk/drivers/block/nbd.c +++ b/trunk/drivers/block/nbd.c @@ -54,15 +54,11 @@ #include #include #include -#include -#include -#include #include #include #include -#include #include #include @@ -140,7 +136,7 @@ static void nbd_end_request(struct request *req) spin_lock_irqsave(q->queue_lock, flags); if (!end_that_request_first(req, uptodate, req->nr_sectors)) { - end_that_request_last(req, uptodate); + end_that_request_last(req); } spin_unlock_irqrestore(q->queue_lock, flags); } @@ -234,6 +230,14 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) request.len = htonl(size); memcpy(request.handle, &req, sizeof(req)); + down(&lo->tx_lock); + + if (!sock || !lo->sock) { + printk(KERN_ERR "%s: Attempted send on closed socket\n", + lo->disk->disk_name); + goto error_out; + } + dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n", lo->disk->disk_name, req, nbdcmd_to_ascii(nbd_cmd(req)), @@ -272,9 +276,11 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) } } } + up(&lo->tx_lock); return 0; error_out: + up(&lo->tx_lock); return 1; } @@ -283,14 +289,9 @@ static struct request *nbd_find_request(struct nbd_device *lo, char *handle) struct request *req; struct list_head *tmp; struct request *xreq; - int err; memcpy(&xreq, handle, sizeof(xreq)); - err = wait_event_interruptible(lo->active_wq, lo->active_req != xreq); - if (unlikely(err)) - goto out; - spin_lock(&lo->queue_lock); list_for_each(tmp, &lo->queue_head) { req = list_entry(tmp, struct request, queuelist); @@ -301,11 +302,7 @@ static struct request *nbd_find_request(struct nbd_device *lo, char *handle) return req; } spin_unlock(&lo->queue_lock); - - err = -ENOENT; - -out: - return ERR_PTR(err); + return NULL; } static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec) @@ -334,11 +331,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo) goto harderror; } req = nbd_find_request(lo, reply.handle); - if (unlikely(IS_ERR(req))) { - result = PTR_ERR(req); - if (result != -ENOENT) - goto harderror; - + if (req == NULL) { printk(KERN_ERR "%s: Unexpected reply (%p)\n", lo->disk->disk_name, reply.handle); result = -EBADR; @@ -402,24 +395,19 @@ static void nbd_clear_que(struct nbd_device *lo) BUG_ON(lo->magic != LO_MAGIC); - /* - * Because we have set lo->sock to NULL under the tx_lock, all - * modifications to the list must have completed by now. For - * the same reason, the active_req must be NULL. - * - * As a consequence, we don't need to take the spin lock while - * purging the list here. - */ - BUG_ON(lo->sock); - BUG_ON(lo->active_req); - - while (!list_empty(&lo->queue_head)) { - req = list_entry(lo->queue_head.next, struct request, - queuelist); - list_del_init(&req->queuelist); - req->errors++; - nbd_end_request(req); - } + do { + req = NULL; + spin_lock(&lo->queue_lock); + if (!list_empty(&lo->queue_head)) { + req = list_entry(lo->queue_head.next, struct request, queuelist); + list_del_init(&req->queuelist); + } + spin_unlock(&lo->queue_lock); + if (req) { + req->errors++; + nbd_end_request(req); + } + } while (req); } /* @@ -447,6 +435,11 @@ static void do_nbd_request(request_queue_t * q) BUG_ON(lo->magic != LO_MAGIC); + if (!lo->file) { + printk(KERN_ERR "%s: Request when not-ready\n", + lo->disk->disk_name); + goto error_out; + } nbd_cmd(req) = NBD_CMD_READ; if (rq_data_dir(req) == WRITE) { nbd_cmd(req) = NBD_CMD_WRITE; @@ -460,34 +453,32 @@ static void do_nbd_request(request_queue_t * q) req->errors = 0; spin_unlock_irq(q->queue_lock); - down(&lo->tx_lock); - if (unlikely(!lo->sock)) { - up(&lo->tx_lock); - printk(KERN_ERR "%s: Attempted send on closed socket\n", - lo->disk->disk_name); + spin_lock(&lo->queue_lock); + + if (!lo->file) { + spin_unlock(&lo->queue_lock); + printk(KERN_ERR "%s: failed between accept and semaphore, file lost\n", + lo->disk->disk_name); req->errors++; nbd_end_request(req); spin_lock_irq(q->queue_lock); continue; } - lo->active_req = req; + list_add(&req->queuelist, &lo->queue_head); + spin_unlock(&lo->queue_lock); if (nbd_send_req(lo, req) != 0) { printk(KERN_ERR "%s: Request send failed\n", lo->disk->disk_name); - req->errors++; - nbd_end_request(req); - } else { - spin_lock(&lo->queue_lock); - list_add(&req->queuelist, &lo->queue_head); - spin_unlock(&lo->queue_lock); + if (nbd_find_request(lo, (char *)&req) != NULL) { + /* we still own req */ + req->errors++; + nbd_end_request(req); + } else /* we're racing with nbd_clear_que */ + printk(KERN_DEBUG "nbd: can't find req\n"); } - lo->active_req = NULL; - up(&lo->tx_lock); - wake_up_all(&lo->active_wq); - spin_lock_irq(q->queue_lock); continue; @@ -538,10 +529,17 @@ static int nbd_ioctl(struct inode *inode, struct file *file, down(&lo->tx_lock); lo->sock = NULL; up(&lo->tx_lock); + spin_lock(&lo->queue_lock); file = lo->file; lo->file = NULL; + spin_unlock(&lo->queue_lock); nbd_clear_que(lo); - BUG_ON(!list_empty(&lo->queue_head)); + spin_lock(&lo->queue_lock); + if (!list_empty(&lo->queue_head)) { + printk(KERN_ERR "nbd: disconnect: some requests are in progress -> please try again.\n"); + error = -EBUSY; + } + spin_unlock(&lo->queue_lock); if (file) fput(file); return error; @@ -600,19 +598,24 @@ static int nbd_ioctl(struct inode *inode, struct file *file, lo->sock = NULL; } up(&lo->tx_lock); + spin_lock(&lo->queue_lock); file = lo->file; lo->file = NULL; + spin_unlock(&lo->queue_lock); nbd_clear_que(lo); printk(KERN_WARNING "%s: queue cleared\n", lo->disk->disk_name); if (file) fput(file); return lo->harderror; case NBD_CLEAR_QUE: - /* - * This is for compatibility only. The queue is always cleared - * by NBD_DO_IT or NBD_CLEAR_SOCK. - */ - BUG_ON(!lo->sock && !list_empty(&lo->queue_head)); + down(&lo->tx_lock); + if (lo->sock) { + up(&lo->tx_lock); + return 0; /* probably should be error, but that would + * break "nbd-client -d", so just return 0 */ + } + up(&lo->tx_lock); + nbd_clear_que(lo); return 0; case NBD_PRINT_DEBUG: printk(KERN_INFO "%s: next = %p, prev = %p, head = %p\n", @@ -685,7 +688,6 @@ static int __init nbd_init(void) spin_lock_init(&nbd_dev[i].queue_lock); INIT_LIST_HEAD(&nbd_dev[i].queue_head); init_MUTEX(&nbd_dev[i].tx_lock); - init_waitqueue_head(&nbd_dev[i].active_wq); nbd_dev[i].blksize = 1024; nbd_dev[i].bytesize = 0x7ffffc00ULL << 10; /* 2TB */ disk->major = NBD_MAJOR; diff --git a/trunk/drivers/block/paride/Kconfig b/trunk/drivers/block/paride/Kconfig index c0d2854dd097..17ff40561257 100644 --- a/trunk/drivers/block/paride/Kconfig +++ b/trunk/drivers/block/paride/Kconfig @@ -4,12 +4,11 @@ # PARIDE doesn't need PARPORT, but if PARPORT is configured as a module, # PARIDE must also be a module. The bogus CONFIG_PARIDE_PARPORT option # controls the choices given to the user ... -# PARIDE only supports PC style parports. Tough for USB or other parports... config PARIDE_PARPORT tristate depends on PARIDE!=n - default m if PARPORT_PC=m - default y if PARPORT_PC!=m + default m if PARPORT=m + default y if PARPORT!=m comment "Parallel IDE high-level drivers" depends on PARIDE diff --git a/trunk/drivers/block/sx8.c b/trunk/drivers/block/sx8.c index 9251f4131b53..1ded3b433459 100644 --- a/trunk/drivers/block/sx8.c +++ b/trunk/drivers/block/sx8.c @@ -770,7 +770,7 @@ static inline void carm_end_request_queued(struct carm_host *host, rc = end_that_request_first(req, uptodate, req->hard_nr_sectors); assert(rc == 0); - end_that_request_last(req, uptodate); + end_that_request_last(req); rc = carm_put_request(host, crq); assert(rc == 0); diff --git a/trunk/drivers/block/ub.c b/trunk/drivers/block/ub.c index a05fe5843e6c..10740a065088 100644 --- a/trunk/drivers/block/ub.c +++ b/trunk/drivers/block/ub.c @@ -951,7 +951,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) static void ub_end_rq(struct request *rq, int uptodate) { end_that_request_first(rq, uptodate, rq->hard_nr_sectors); - end_that_request_last(rq, uptodate); + end_that_request_last(rq); } static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, diff --git a/trunk/drivers/block/viodasd.c b/trunk/drivers/block/viodasd.c index 063f0304a163..2d518aa2720a 100644 --- a/trunk/drivers/block/viodasd.c +++ b/trunk/drivers/block/viodasd.c @@ -305,7 +305,7 @@ static void viodasd_end_request(struct request *req, int uptodate, if (end_that_request_first(req, uptodate, num_sectors)) return; add_disk_randomness(req->rq_disk); - end_that_request_last(req, uptodate); + end_that_request_last(req); } /* diff --git a/trunk/drivers/cdrom/cdu31a.c b/trunk/drivers/cdrom/cdu31a.c index 378e88d20757..ac96de15d833 100644 --- a/trunk/drivers/cdrom/cdu31a.c +++ b/trunk/drivers/cdrom/cdu31a.c @@ -1402,7 +1402,7 @@ static void do_cdu31a_request(request_queue_t * q) if (!end_that_request_first(req, 1, nblock)) { spin_lock_irq(q->queue_lock); blkdev_dequeue_request(req); - end_that_request_last(req, 1); + end_that_request_last(req); spin_unlock_irq(q->queue_lock); } continue; diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index 5ebd06b1b4ca..84e68cdd451b 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -985,7 +985,7 @@ config HPET_MMAP config HANGCHECK_TIMER tristate "Hangcheck timer" - depends on X86 || IA64 || PPC64 || S390 + depends on X86 || IA64 || PPC64 || ARCH_S390 help The hangcheck-timer module detects when the system has gone out to lunch past a certain margin. It can reboot the system diff --git a/trunk/drivers/char/hangcheck-timer.c b/trunk/drivers/char/hangcheck-timer.c index 40a67c86420c..66e53dd450ff 100644 --- a/trunk/drivers/char/hangcheck-timer.c +++ b/trunk/drivers/char/hangcheck-timer.c @@ -120,7 +120,7 @@ __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks); #if defined(CONFIG_X86) # define HAVE_MONOTONIC # define TIMER_FREQ 1000000000ULL -#elif defined(CONFIG_S390) +#elif defined(CONFIG_ARCH_S390) /* FA240000 is 1 Second in the IBM time universe (Page 4-38 Principles of Op for zSeries */ # define TIMER_FREQ 0xFA240000ULL #elif defined(CONFIG_IA64) diff --git a/trunk/drivers/char/hw_random.c b/trunk/drivers/char/hw_random.c index 49769f59ea1b..6f673d2de0b1 100644 --- a/trunk/drivers/char/hw_random.c +++ b/trunk/drivers/char/hw_random.c @@ -1,9 +1,4 @@ /* - Added support for the AMD Geode LX RNG - (c) Copyright 2004-2005 Advanced Micro Devices, Inc. - - derived from - Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) (c) Copyright 2003 Red Hat Inc @@ -100,11 +95,6 @@ static unsigned int via_data_present (void); static u32 via_data_read (void); #endif -static int __init geode_init(struct pci_dev *dev); -static void geode_cleanup(void); -static unsigned int geode_data_present (void); -static u32 geode_data_read (void); - struct rng_operations { int (*init) (struct pci_dev *dev); void (*cleanup) (void); @@ -132,7 +122,6 @@ enum { rng_hw_intel, rng_hw_amd, rng_hw_via, - rng_hw_geode, }; static struct rng_operations rng_vendor_ops[] = { @@ -150,9 +139,6 @@ static struct rng_operations rng_vendor_ops[] = { /* rng_hw_via */ { via_init, via_cleanup, via_data_present, via_data_read, 1 }, #endif - - /* rng_hw_geode */ - { geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 } }; /* @@ -173,9 +159,6 @@ static struct pci_device_id rng_pci_tbl[] = { { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode }, - { 0, }, /* terminate list */ }; MODULE_DEVICE_TABLE (pci, rng_pci_tbl); @@ -477,57 +460,6 @@ static void via_cleanup(void) } #endif -/*********************************************************************** - * - * AMD Geode RNG operations - * - */ - -static void __iomem *geode_rng_base = NULL; - -#define GEODE_RNG_DATA_REG 0x50 -#define GEODE_RNG_STATUS_REG 0x54 - -static u32 geode_data_read(void) -{ - u32 val; - - assert(geode_rng_base != NULL); - val = readl(geode_rng_base + GEODE_RNG_DATA_REG); - return val; -} - -static unsigned int geode_data_present(void) -{ - u32 val; - - assert(geode_rng_base != NULL); - val = readl(geode_rng_base + GEODE_RNG_STATUS_REG); - return val; -} - -static void geode_cleanup(void) -{ - iounmap(geode_rng_base); - geode_rng_base = NULL; -} - -static int geode_init(struct pci_dev *dev) -{ - unsigned long rng_base = pci_resource_start(dev, 0); - - if (rng_base == 0) - return 1; - - geode_rng_base = ioremap(rng_base, 0x58); - - if (geode_rng_base == NULL) { - printk(KERN_ERR PFX "Cannot ioremap RNG memory\n"); - return -EBUSY; - } - - return 0; -} /*********************************************************************** * @@ -642,7 +574,7 @@ static int __init rng_init (void) DPRINTK ("ENTER\n"); - /* Probe for Intel, AMD, Geode RNGs */ + /* Probe for Intel, AMD RNGs */ for_each_pci_dev(pdev) { ent = pci_match_id(rng_pci_tbl, pdev); if (ent) { diff --git a/trunk/drivers/char/ipmi/ipmi_msghandler.c b/trunk/drivers/char/ipmi/ipmi_msghandler.c index 561430ed94af..1f56b4cf0f58 100644 --- a/trunk/drivers/char/ipmi/ipmi_msghandler.c +++ b/trunk/drivers/char/ipmi/ipmi_msghandler.c @@ -787,6 +787,7 @@ int ipmi_destroy_user(ipmi_user_t user) int i; unsigned long flags; struct cmd_rcvr *rcvr; + struct list_head *entry1, *entry2; struct cmd_rcvr *rcvrs = NULL; user->valid = 1; @@ -811,7 +812,8 @@ int ipmi_destroy_user(ipmi_user_t user) * synchronize_rcu()) then free everything in that list. */ down(&intf->cmd_rcvrs_lock); - list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { + list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) { + rcvr = list_entry(entry1, struct cmd_rcvr, link); if (rcvr->user == user) { list_del_rcu(&rcvr->link); rcvr->next = rcvrs; diff --git a/trunk/drivers/char/mmtimer.c b/trunk/drivers/char/mmtimer.c index c92378121b4c..78c89a3e7825 100644 --- a/trunk/drivers/char/mmtimer.c +++ b/trunk/drivers/char/mmtimer.c @@ -1,11 +1,11 @@ /* - * Timer device implementation for SGI SN platforms. + * Intel Multimedia Timer device implementation for SGI SN platforms. * * 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 archive * for more details. * - * Copyright (c) 2001-2006 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 2001-2004 Silicon Graphics, Inc. All rights reserved. * * This driver exports an API that should be supportable by any HPET or IA-PC * multimedia timer. The code below is currently specific to the SGI Altix @@ -45,7 +45,7 @@ MODULE_LICENSE("GPL"); /* name of the device, usually in /dev */ #define MMTIMER_NAME "mmtimer" #define MMTIMER_DESC "SGI Altix RTC Timer" -#define MMTIMER_VERSION "2.1" +#define MMTIMER_VERSION "2.0" #define RTC_BITS 55 /* 55 bits for this implementation */ @@ -227,7 +227,10 @@ typedef struct mmtimer { struct tasklet_struct tasklet; } mmtimer_t; -static mmtimer_t ** timers; +/* + * Total number of comparators is comparators/node * MAX nodes/running kernel + */ +static mmtimer_t timers[NUM_COMPARATORS*MAX_COMPACT_NODES]; /** * mmtimer_ioctl - ioctl interface for /dev/mmtimer @@ -438,29 +441,29 @@ static irqreturn_t mmtimer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int i; + mmtimer_t *base = timers + cpu_to_node(smp_processor_id()) * + NUM_COMPARATORS; unsigned long expires = 0; int result = IRQ_NONE; - unsigned indx = cpu_to_node(smp_processor_id()); /* * Do this once for each comparison register */ for (i = 0; i < NUM_COMPARATORS; i++) { - mmtimer_t *base = timers[indx] + i; /* Make sure this doesn't get reused before tasklet_sched */ - spin_lock(&base->lock); - if (base->cpu == smp_processor_id()) { - if (base->timer) - expires = base->timer->it.mmtimer.expires; + spin_lock(&base[i].lock); + if (base[i].cpu == smp_processor_id()) { + if (base[i].timer) + expires = base[i].timer->it.mmtimer.expires; /* expires test won't work with shared irqs */ if ((mmtimer_int_pending(i) > 0) || (expires && (expires < rtc_time()))) { mmtimer_clr_int_pending(i); - tasklet_schedule(&base->tasklet); + tasklet_schedule(&base[i].tasklet); result = IRQ_HANDLED; } } - spin_unlock(&base->lock); + spin_unlock(&base[i].lock); expires = 0; } return result; @@ -520,7 +523,7 @@ static int sgi_timer_del(struct k_itimer *timr) { int i = timr->it.mmtimer.clock; cnodeid_t nodeid = timr->it.mmtimer.node; - mmtimer_t *t = timers[nodeid] + i; + mmtimer_t *t = timers + nodeid * NUM_COMPARATORS +i; unsigned long irqflags; if (i != TIMER_OFF) { @@ -606,11 +609,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, preempt_disable(); nodeid = cpu_to_node(smp_processor_id()); + base = timers + nodeid * NUM_COMPARATORS; retry: /* Don't use an allocated timer, or a deleted one that's pending */ for(i = 0; i< NUM_COMPARATORS; i++) { - base = timers[nodeid] + i; - if (!base->timer && !base->tasklet.state) { + if (!base[i].timer && !base[i].tasklet.state) { break; } } @@ -620,14 +623,14 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, return -EBUSY; } - spin_lock_irqsave(&base->lock, irqflags); + spin_lock_irqsave(&base[i].lock, irqflags); - if (base->timer || base->tasklet.state != 0) { - spin_unlock_irqrestore(&base->lock, irqflags); + if (base[i].timer || base[i].tasklet.state != 0) { + spin_unlock_irqrestore(&base[i].lock, irqflags); goto retry; } - base->timer = timr; - base->cpu = smp_processor_id(); + base[i].timer = timr; + base[i].cpu = smp_processor_id(); timr->it.mmtimer.clock = i; timr->it.mmtimer.node = nodeid; @@ -642,11 +645,11 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, } } else { timr->it.mmtimer.expires -= period; - if (reschedule_periodic_timer(base)) + if (reschedule_periodic_timer(base+i)) err = -EINVAL; } - spin_unlock_irqrestore(&base->lock, irqflags); + spin_unlock_irqrestore(&base[i].lock, irqflags); preempt_enable(); @@ -672,7 +675,6 @@ static struct k_clock sgi_clock = { static int __init mmtimer_init(void) { unsigned i; - cnodeid_t node, maxn = -1; if (!ia64_platform_is("sn2")) return -1; @@ -689,6 +691,14 @@ static int __init mmtimer_init(void) mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second / 2) / sn_rtc_cycles_per_second; + for (i=0; i< NUM_COMPARATORS*MAX_COMPACT_NODES; i++) { + spin_lock_init(&timers[i].lock); + timers[i].timer = NULL; + timers[i].cpu = 0; + timers[i].i = i % NUM_COMPARATORS; + tasklet_init(&timers[i].tasklet, mmtimer_tasklet, (unsigned long) (timers+i)); + } + if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, SA_PERCPU_IRQ, MMTIMER_NAME, NULL)) { printk(KERN_WARNING "%s: unable to allocate interrupt.", MMTIMER_NAME); @@ -702,40 +712,6 @@ static int __init mmtimer_init(void) return -1; } - /* Get max numbered node, calculate slots needed */ - for_each_online_node(node) { - maxn = node; - } - maxn++; - - /* Allocate list of node ptrs to mmtimer_t's */ - timers = kmalloc(sizeof(mmtimer_t *)*maxn, GFP_KERNEL); - if (timers == NULL) { - printk(KERN_ERR "%s: failed to allocate memory for device\n", - MMTIMER_NAME); - return -1; - } - - /* Allocate mmtimer_t's for each online node */ - for_each_online_node(node) { - timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node); - if (timers[node] == NULL) { - printk(KERN_ERR "%s: failed to allocate memory for device\n", - MMTIMER_NAME); - return -1; - } - for (i=0; i< NUM_COMPARATORS; i++) { - mmtimer_t * base = timers[node] + i; - - spin_lock_init(&base->lock); - base->timer = NULL; - base->cpu = 0; - base->i = i; - tasklet_init(&base->tasklet, mmtimer_tasklet, - (unsigned long) (base)); - } - } - sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second; register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock); diff --git a/trunk/drivers/char/watchdog/Kconfig b/trunk/drivers/char/watchdog/Kconfig index a6544790af60..344001b45af9 100644 --- a/trunk/drivers/char/watchdog/Kconfig +++ b/trunk/drivers/char/watchdog/Kconfig @@ -438,7 +438,7 @@ config INDYDOG config ZVM_WATCHDOG tristate "z/VM Watchdog Timer" - depends on WATCHDOG && S390 + depends on WATCHDOG && ARCH_S390 help IBM s/390 and zSeries machines running under z/VM 5.1 or later provide a virtual watchdog timer to their guest that cause a diff --git a/trunk/drivers/ide/ide-cd.c b/trunk/drivers/ide/ide-cd.c index d31117eb95aa..70aeb3a60120 100644 --- a/trunk/drivers/ide/ide-cd.c +++ b/trunk/drivers/ide/ide-cd.c @@ -614,7 +614,7 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate) */ spin_lock_irqsave(&ide_lock, flags); end_that_request_chunk(failed, 0, failed->data_len); - end_that_request_last(failed, 0); + end_that_request_last(failed); spin_unlock_irqrestore(&ide_lock, flags); } @@ -1735,7 +1735,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) spin_lock_irqsave(&ide_lock, flags); blkdev_dequeue_request(rq); - end_that_request_last(rq, 1); + end_that_request_last(rq); HWGROUP(drive)->rq = NULL; spin_unlock_irqrestore(&ide_lock, flags); return ide_stopped; diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index 4b441720b6ba..4e5767968d7f 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -681,9 +681,50 @@ static ide_proc_entry_t idedisk_proc[] = { #endif /* CONFIG_PROC_FS */ -static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) +static void idedisk_end_flush(request_queue_t *q, struct request *flush_rq) { ide_drive_t *drive = q->queuedata; + struct request *rq = flush_rq->end_io_data; + int good_sectors = rq->hard_nr_sectors; + int bad_sectors; + sector_t sector; + + if (flush_rq->errors & ABRT_ERR) { + printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name); + blk_queue_ordered(drive->queue, QUEUE_ORDERED_NONE); + blk_queue_issue_flush_fn(drive->queue, NULL); + good_sectors = 0; + } else if (flush_rq->errors) { + good_sectors = 0; + if (blk_barrier_preflush(rq)) { + sector = ide_get_error_location(drive,flush_rq->buffer); + if ((sector >= rq->hard_sector) && + (sector < rq->hard_sector + rq->hard_nr_sectors)) + good_sectors = sector - rq->hard_sector; + } + } + + if (flush_rq->errors) + printk(KERN_ERR "%s: failed barrier write: " + "sector=%Lx(good=%d/bad=%d)\n", + drive->name, (unsigned long long)rq->sector, + good_sectors, + (int) (rq->hard_nr_sectors-good_sectors)); + + bad_sectors = rq->hard_nr_sectors - good_sectors; + + if (good_sectors) + __ide_end_request(drive, rq, 1, good_sectors); + if (bad_sectors) + __ide_end_request(drive, rq, 0, bad_sectors); +} + +static int idedisk_prepare_flush(request_queue_t *q, struct request *rq) +{ + ide_drive_t *drive = q->queuedata; + + if (!drive->wcache) + return 0; memset(rq->cmd, 0, sizeof(rq->cmd)); @@ -694,8 +735,9 @@ static void idedisk_prepare_flush(request_queue_t *q, struct request *rq) rq->cmd[0] = WIN_FLUSH_CACHE; - rq->flags |= REQ_DRIVE_TASK; + rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER; rq->buffer = rq->cmd; + return 1; } static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk, @@ -752,64 +794,27 @@ static int set_nowerr(ide_drive_t *drive, int arg) return 0; } -static void update_ordered(ide_drive_t *drive) -{ - struct hd_driveid *id = drive->id; - unsigned ordered = QUEUE_ORDERED_NONE; - prepare_flush_fn *prep_fn = NULL; - issue_flush_fn *issue_fn = NULL; - - if (drive->wcache) { - unsigned long long capacity; - int barrier; - /* - * We must avoid issuing commands a drive does not - * understand or we may crash it. We check flush cache - * is supported. We also check we have the LBA48 flush - * cache if the drive capacity is too large. By this - * time we have trimmed the drive capacity if LBA48 is - * not available so we don't need to recheck that. - */ - capacity = idedisk_capacity(drive); - barrier = ide_id_has_flush_cache(id) && - (drive->addressing == 0 || capacity <= (1ULL << 28) || - ide_id_has_flush_cache_ext(id)); - - printk(KERN_INFO "%s: cache flushes %ssupported\n", - drive->name, barrier ? "" : "not"); - - if (barrier) { - ordered = QUEUE_ORDERED_DRAIN_FLUSH; - prep_fn = idedisk_prepare_flush; - issue_fn = idedisk_issue_flush; - } - } else - ordered = QUEUE_ORDERED_DRAIN; - - blk_queue_ordered(drive->queue, ordered, prep_fn); - blk_queue_issue_flush_fn(drive->queue, issue_fn); -} - static int write_cache(ide_drive_t *drive, int arg) { ide_task_t args; - int err = 1; + int err; - if (ide_id_has_flush_cache(drive->id)) { - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? + if (!ide_id_has_flush_cache(drive->id)) + return 1; + + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; - args.command_type = IDE_DRIVE_TASK_NO_DATA; - args.handler = &task_no_data_intr; - err = ide_raw_taskfile(drive, &args, NULL); - if (err == 0) - drive->wcache = arg; - } + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; + args.command_type = IDE_DRIVE_TASK_NO_DATA; + args.handler = &task_no_data_intr; - update_ordered(drive); + err = ide_raw_taskfile(drive, &args, NULL); + if (err) + return err; - return err; + drive->wcache = arg; + return 0; } static int do_idedisk_flushcache (ide_drive_t *drive) @@ -883,6 +888,7 @@ static void idedisk_setup (ide_drive_t *drive) { struct hd_driveid *id = drive->id; unsigned long long capacity; + int barrier; idedisk_add_settings(drive); @@ -986,6 +992,31 @@ static void idedisk_setup (ide_drive_t *drive) drive->wcache = 1; write_cache(drive, 1); + + /* + * We must avoid issuing commands a drive does not understand + * or we may crash it. We check flush cache is supported. We also + * check we have the LBA48 flush cache if the drive capacity is + * too large. By this time we have trimmed the drive capacity if + * LBA48 is not available so we don't need to recheck that. + */ + barrier = 0; + if (ide_id_has_flush_cache(id)) + barrier = 1; + if (drive->addressing == 1) { + /* Can't issue the correct flush ? */ + if (capacity > (1ULL << 28) && !ide_id_has_flush_cache_ext(id)) + barrier = 0; + } + + printk(KERN_INFO "%s: cache flushes %ssupported\n", + drive->name, barrier ? "" : "not "); + if (barrier) { + blk_queue_ordered(drive->queue, QUEUE_ORDERED_FLUSH); + drive->queue->prepare_flush_fn = idedisk_prepare_flush; + drive->queue->end_flush_fn = idedisk_end_flush; + blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush); + } } static void ide_cacheflush_p(ide_drive_t *drive) diff --git a/trunk/drivers/ide/ide-io.c b/trunk/drivers/ide/ide-io.c index b5dc6df8e67d..ecfafcdafea4 100644 --- a/trunk/drivers/ide/ide-io.c +++ b/trunk/drivers/ide/ide-io.c @@ -89,7 +89,7 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; - end_that_request_last(rq, uptodate); + end_that_request_last(rq); ret = 0; } return ret; @@ -119,7 +119,10 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) if (!nr_sectors) nr_sectors = rq->hard_cur_sectors; - ret = __ide_end_request(drive, rq, uptodate, nr_sectors); + if (blk_complete_barrier_rq_locked(drive->queue, rq, nr_sectors)) + ret = rq->nr_sectors != 0; + else + ret = __ide_end_request(drive, rq, uptodate, nr_sectors); spin_unlock_irqrestore(&ide_lock, flags); return ret; @@ -244,7 +247,7 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq) } blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; - end_that_request_last(rq, 1); + end_that_request_last(rq); spin_unlock_irqrestore(&ide_lock, flags); } @@ -376,7 +379,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; rq->errors = err; - end_that_request_last(rq, !rq->errors); + end_that_request_last(rq); spin_unlock_irqrestore(&ide_lock, flags); } diff --git a/trunk/drivers/ieee1394/ieee1394_core.c b/trunk/drivers/ieee1394/ieee1394_core.c index 25ef5a86f5f0..64fbbb01d52a 100644 --- a/trunk/drivers/ieee1394/ieee1394_core.c +++ b/trunk/drivers/ieee1394/ieee1394_core.c @@ -1027,10 +1027,10 @@ static int hpsbpkt_thread(void *__hi) daemonize("khpsbpkt"); - current->flags |= PF_NOFREEZE; - while (1) { if (down_interruptible(&khpsbpkt_sig)) { + if (try_to_freeze()) + continue; printk("khpsbpkt: received unexpected signal?!\n" ); break; } diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c index a1e660e3531d..9f2352bd8348 100644 --- a/trunk/drivers/input/evdev.c +++ b/trunk/drivers/input/evdev.c @@ -157,7 +157,7 @@ struct input_event_compat { # define COMPAT_TEST test_thread_flag(TIF_IA32) #elif defined(CONFIG_IA64) # define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) -#elif defined(CONFIG_S390) +#elif defined(CONFIG_ARCH_S390) # define COMPAT_TEST test_thread_flag(TIF_31BIT) #elif defined(CONFIG_MIPS) # define COMPAT_TEST (current->thread.mflags & MF_32BIT_ADDR) diff --git a/trunk/drivers/macintosh/therm_adt746x.c b/trunk/drivers/macintosh/therm_adt746x.c index 5e1f5e9653cb..f38696622eb4 100644 --- a/trunk/drivers/macintosh/therm_adt746x.c +++ b/trunk/drivers/macintosh/therm_adt746x.c @@ -52,7 +52,6 @@ static char *sensor_location[3] = {NULL, NULL, NULL}; static int limit_adjust = 0; static int fan_speed = -1; -static int verbose = 0; MODULE_AUTHOR("Colin Leroy "); MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and " @@ -67,10 +66,6 @@ module_param(fan_speed, int, 0644); MODULE_PARM_DESC(fan_speed,"Specify starting fan speed (0-255) " "(default 64)"); -module_param(verbose, bool, 0); -MODULE_PARM_DESC(verbose,"Verbose log operations " - "(default 0)"); - struct thermostat { struct i2c_client clt; u8 temps[3]; @@ -154,13 +149,13 @@ detach_thermostat(struct i2c_adapter *adapter) if (thread_therm != NULL) { kthread_stop(thread_therm); } - + printk(KERN_INFO "adt746x: Putting max temperatures back from " "%d, %d, %d to %d, %d, %d\n", th->limits[0], th->limits[1], th->limits[2], th->initial_limits[0], th->initial_limits[1], th->initial_limits[2]); - + for (i = 0; i < 3; i++) write_reg(th, LIMIT_REG[i], th->initial_limits[i]); @@ -217,14 +212,12 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan) return; if (th->last_speed[fan] != speed) { - if (verbose) { - if (speed == -1) - printk(KERN_DEBUG "adt746x: Setting speed to automatic " - "for %s fan.\n", sensor_location[fan+1]); - else - printk(KERN_DEBUG "adt746x: Setting speed to %d " - "for %s fan.\n", speed, sensor_location[fan+1]); - } + if (speed == -1) + printk(KERN_DEBUG "adt746x: Setting speed to automatic " + "for %s fan.\n", sensor_location[fan+1]); + else + printk(KERN_DEBUG "adt746x: Setting speed to %d " + "for %s fan.\n", speed, sensor_location[fan+1]); } else return; @@ -305,11 +298,10 @@ static void update_fans_speed (struct thermostat *th) if (new_speed > 255) new_speed = 255; - if (verbose) - printk(KERN_DEBUG "adt746x: Setting fans speed to %d " - "(limit exceeded by %d on %s) \n", - new_speed, var, - sensor_location[fan_number+1]); + printk(KERN_DEBUG "adt746x: setting fans speed to %d " + "(limit exceeded by %d on %s) \n", + new_speed, var, + sensor_location[fan_number+1]); write_both_fan_speed(th, new_speed); th->last_var[fan_number] = var; } else if (var < -2) { @@ -317,9 +309,8 @@ static void update_fans_speed (struct thermostat *th) * so cold (lastvar >= -1) */ if (i == 2 && lastvar < -1) { if (th->last_speed[fan_number] != 0) - if (verbose) - printk(KERN_DEBUG "adt746x: Stopping " - "fans.\n"); + printk(KERN_DEBUG "adt746x: Stopping " + "fans.\n"); write_both_fan_speed(th, 0); } } @@ -415,7 +406,7 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr, th->initial_limits[i] = read_reg(th, LIMIT_REG[i]); set_limit(th, i); } - + printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d" " to %d, %d, %d\n", th->initial_limits[0], th->initial_limits[1], diff --git a/trunk/drivers/macintosh/therm_pm72.c b/trunk/drivers/macintosh/therm_pm72.c index 435427daed75..190878eef990 100644 --- a/trunk/drivers/macintosh/therm_pm72.c +++ b/trunk/drivers/macintosh/therm_pm72.c @@ -1988,13 +1988,18 @@ static void fcu_lookup_fans(struct device_node *fcu_node) static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match) { + int rc; + state = state_detached; /* Lookup the fans in the device tree */ fcu_lookup_fans(dev->node); /* Add the driver */ - return i2c_add_driver(&therm_pm72_driver); + rc = i2c_add_driver(&therm_pm72_driver); + if (rc < 0) + return rc; + return 0; } static int fcu_of_remove(struct of_device* dev) diff --git a/trunk/drivers/macintosh/windfarm_lm75_sensor.c b/trunk/drivers/macintosh/windfarm_lm75_sensor.c index c62ed68a3138..a0a41ad0f2b5 100644 --- a/trunk/drivers/macintosh/windfarm_lm75_sensor.c +++ b/trunk/drivers/macintosh/windfarm_lm75_sensor.c @@ -240,7 +240,12 @@ static int wf_lm75_detach(struct i2c_client *client) static int __init wf_lm75_sensor_init(void) { - return i2c_add_driver(&wf_lm75_driver); + int rc; + + rc = i2c_add_driver(&wf_lm75_driver); + if (rc < 0) + return rc; + return 0; } static void __exit wf_lm75_sensor_exit(void) diff --git a/trunk/drivers/md/bitmap.c b/trunk/drivers/md/bitmap.c index 76a189ceb529..252d55df9642 100644 --- a/trunk/drivers/md/bitmap.c +++ b/trunk/drivers/md/bitmap.c @@ -315,8 +315,6 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait) if (bitmap->file == NULL) return write_sb_page(bitmap->mddev, bitmap->offset, page, wait); - flush_dcache_page(page); /* make sure visible to anyone reading the file */ - if (wait) lock_page(page); else { @@ -343,7 +341,7 @@ static int write_page(struct bitmap *bitmap, struct page *page, int wait) /* add to list to be waited for by daemon */ struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO); item->page = page; - get_page(page); + page_cache_get(page); spin_lock(&bitmap->write_lock); list_add(&item->list, &bitmap->complete_pages); spin_unlock(&bitmap->write_lock); @@ -359,10 +357,10 @@ static struct page *read_page(struct file *file, unsigned long index, struct inode *inode = file->f_mapping->host; struct page *page = NULL; loff_t isize = i_size_read(inode); - unsigned long end_index = isize >> PAGE_SHIFT; + unsigned long end_index = isize >> PAGE_CACHE_SHIFT; - PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_SIZE, - (unsigned long long)index << PAGE_SHIFT); + PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_CACHE_SIZE, + (unsigned long long)index << PAGE_CACHE_SHIFT); page = read_cache_page(inode->i_mapping, index, (filler_t *)inode->i_mapping->a_ops->readpage, file); @@ -370,7 +368,7 @@ static struct page *read_page(struct file *file, unsigned long index, goto out; wait_on_page_locked(page); if (!PageUptodate(page) || PageError(page)) { - put_page(page); + page_cache_release(page); page = ERR_PTR(-EIO); goto out; } @@ -378,14 +376,14 @@ static struct page *read_page(struct file *file, unsigned long index, if (index > end_index) /* we have read beyond EOF */ *bytes_read = 0; else if (index == end_index) /* possible short read */ - *bytes_read = isize & ~PAGE_MASK; + *bytes_read = isize & ~PAGE_CACHE_MASK; else - *bytes_read = PAGE_SIZE; /* got a full page */ + *bytes_read = PAGE_CACHE_SIZE; /* got a full page */ out: if (IS_ERR(page)) printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n", - (int)PAGE_SIZE, - (unsigned long long)index << PAGE_SHIFT, + (int)PAGE_CACHE_SIZE, + (unsigned long long)index << PAGE_CACHE_SHIFT, PTR_ERR(page)); return page; } @@ -408,11 +406,11 @@ int bitmap_update_sb(struct bitmap *bitmap) return 0; } spin_unlock_irqrestore(&bitmap->lock, flags); - sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); + sb = (bitmap_super_t *)kmap(bitmap->sb_page); sb->events = cpu_to_le64(bitmap->mddev->events); if (!bitmap->mddev->degraded) sb->events_cleared = cpu_to_le64(bitmap->mddev->events); - kunmap_atomic(sb, KM_USER0); + kunmap(bitmap->sb_page); return write_page(bitmap, bitmap->sb_page, 1); } @@ -423,7 +421,7 @@ void bitmap_print_sb(struct bitmap *bitmap) if (!bitmap || !bitmap->sb_page) return; - sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); + sb = (bitmap_super_t *)kmap(bitmap->sb_page); printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap)); printk(KERN_DEBUG " magic: %08x\n", le32_to_cpu(sb->magic)); printk(KERN_DEBUG " version: %d\n", le32_to_cpu(sb->version)); @@ -442,7 +440,7 @@ void bitmap_print_sb(struct bitmap *bitmap) printk(KERN_DEBUG " sync size: %llu KB\n", (unsigned long long)le64_to_cpu(sb->sync_size)/2); printk(KERN_DEBUG "max write behind: %d\n", le32_to_cpu(sb->write_behind)); - kunmap_atomic(sb, KM_USER0); + kunmap(bitmap->sb_page); } /* read the superblock from the bitmap file and initialize some bitmap fields */ @@ -468,7 +466,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) return err; } - sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); + sb = (bitmap_super_t *)kmap(bitmap->sb_page); if (bytes_read < sizeof(*sb)) { /* short read */ printk(KERN_INFO "%s: bitmap file superblock truncated\n", @@ -487,12 +485,12 @@ static int bitmap_read_sb(struct bitmap *bitmap) else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO || le32_to_cpu(sb->version) > BITMAP_MAJOR_HI) reason = "unrecognized superblock version"; - else if (chunksize < PAGE_SIZE) - reason = "bitmap chunksize too small"; + else if (chunksize < 512 || chunksize > (1024 * 1024 * 4)) + reason = "bitmap chunksize out of range (512B - 4MB)"; else if ((1 << ffz(~chunksize)) != chunksize) reason = "bitmap chunksize not a power of 2"; - else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT / HZ) - reason = "daemon sleep period out of range"; + else if (daemon_sleep < 1 || daemon_sleep > 15) + reason = "daemon sleep period out of range (1-15s)"; else if (write_behind > COUNTER_MAX) reason = "write-behind limit out of range (0 - 16383)"; if (reason) { @@ -537,7 +535,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) bitmap->events_cleared = bitmap->mddev->events; err = 0; out: - kunmap_atomic(sb, KM_USER0); + kunmap(bitmap->sb_page); if (err) bitmap_print_sb(bitmap); return err; @@ -560,9 +558,9 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits, spin_unlock_irqrestore(&bitmap->lock, flags); return; } - get_page(bitmap->sb_page); + page_cache_get(bitmap->sb_page); spin_unlock_irqrestore(&bitmap->lock, flags); - sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); + sb = (bitmap_super_t *)kmap(bitmap->sb_page); switch (op) { case MASK_SET: sb->state |= bits; break; @@ -570,8 +568,8 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits, break; default: BUG(); } - kunmap_atomic(sb, KM_USER0); - put_page(bitmap->sb_page); + kunmap(bitmap->sb_page); + page_cache_release(bitmap->sb_page); } /* @@ -624,11 +622,12 @@ static void bitmap_file_unmap(struct bitmap *bitmap) while (pages--) if (map[pages]->index != 0) /* 0 is sb_page, release it below */ - put_page(map[pages]); + page_cache_release(map[pages]); kfree(map); kfree(attr); - safe_put_page(sb_page); + if (sb_page) + page_cache_release(sb_page); } static void bitmap_stop_daemon(struct bitmap *bitmap); @@ -655,7 +654,7 @@ static void drain_write_queues(struct bitmap *bitmap) while ((item = dequeue_page(bitmap))) { /* don't bother to wait */ - put_page(item->page); + page_cache_release(item->page); mempool_free(item, bitmap->write_pool); } @@ -764,7 +763,7 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) /* make sure the page stays cached until it gets written out */ if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY)) - get_page(page); + page_cache_get(page); /* set the bit */ kaddr = kmap_atomic(page, KM_USER0); @@ -855,7 +854,6 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) unsigned long bytes, offset, dummy; int outofdate; int ret = -ENOSPC; - void *paddr; chunks = bitmap->chunks; file = bitmap->file; @@ -889,10 +887,12 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) if (!bitmap->filemap) goto out; - bitmap->filemap_attr = kzalloc(sizeof(long) * num_pages, GFP_KERNEL); + bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL); if (!bitmap->filemap_attr) goto out; + memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages); + oldindex = ~0L; for (i = 0; i < chunks; i++) { @@ -901,6 +901,8 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) bit = file_page_offset(i); if (index != oldindex) { /* this is a new page, read it in */ /* unmap the old page, we're done with it */ + if (oldpage != NULL) + kunmap(oldpage); if (index == 0) { /* * if we're here then the superblock page @@ -923,32 +925,30 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) oldindex = index; oldpage = page; + kmap(page); if (outofdate) { /* * if bitmap is out of date, dirty the * whole page and write it out */ - paddr = kmap_atomic(page, KM_USER0); - memset(paddr + offset, 0xff, + memset(page_address(page) + offset, 0xff, PAGE_SIZE - offset); - kunmap_atomic(paddr, KM_USER0); ret = write_page(bitmap, page, 1); if (ret) { + kunmap(page); /* release, page not in filemap yet */ - put_page(page); + page_cache_release(page); goto out; } } bitmap->filemap[bitmap->file_pages++] = page; } - paddr = kmap_atomic(page, KM_USER0); if (bitmap->flags & BITMAP_HOSTENDIAN) - b = test_bit(bit, paddr); + b = test_bit(bit, page_address(page)); else - b = ext2_test_bit(bit, paddr); - kunmap_atomic(paddr, KM_USER0); + b = ext2_test_bit(bit, page_address(page)); if (b) { /* if the disk bit is set, set the memory bit */ bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap), @@ -963,6 +963,9 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) ret = 0; bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET); + if (page) /* unmap the last page */ + kunmap(page); + if (bit_cnt) { /* Kick recovery if any bits were set */ set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery); md_wakeup_thread(bitmap->mddev->thread); @@ -1018,7 +1021,6 @@ int bitmap_daemon_work(struct bitmap *bitmap) int err = 0; int blocks; int attr; - void *paddr; if (bitmap == NULL) return 0; @@ -1041,7 +1043,7 @@ int bitmap_daemon_work(struct bitmap *bitmap) /* skip this page unless it's marked as needing cleaning */ if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) { if (attr & BITMAP_PAGE_NEEDWRITE) { - get_page(page); + page_cache_get(page); clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE); } spin_unlock_irqrestore(&bitmap->lock, flags); @@ -1055,13 +1057,13 @@ int bitmap_daemon_work(struct bitmap *bitmap) default: bitmap_file_kick(bitmap); } - put_page(page); + page_cache_release(page); } continue; } /* grab the new page, sync and release the old */ - get_page(page); + page_cache_get(page); if (lastpage != NULL) { if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) { clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); @@ -1075,12 +1077,14 @@ int bitmap_daemon_work(struct bitmap *bitmap) set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); spin_unlock_irqrestore(&bitmap->lock, flags); } - put_page(lastpage); + kunmap(lastpage); + page_cache_release(lastpage); if (err) bitmap_file_kick(bitmap); } else spin_unlock_irqrestore(&bitmap->lock, flags); lastpage = page; + kmap(page); /* printk("bitmap clean at page %lu\n", j); */ @@ -1103,12 +1107,10 @@ int bitmap_daemon_work(struct bitmap *bitmap) -1); /* clear the bit */ - paddr = kmap_atomic(page, KM_USER0); if (bitmap->flags & BITMAP_HOSTENDIAN) - clear_bit(file_page_offset(j), paddr); + clear_bit(file_page_offset(j), page_address(page)); else - ext2_clear_bit(file_page_offset(j), paddr); - kunmap_atomic(paddr, KM_USER0); + ext2_clear_bit(file_page_offset(j), page_address(page)); } } spin_unlock_irqrestore(&bitmap->lock, flags); @@ -1116,6 +1118,7 @@ int bitmap_daemon_work(struct bitmap *bitmap) /* now sync the final page */ if (lastpage != NULL) { + kunmap(lastpage); spin_lock_irqsave(&bitmap->lock, flags); if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) { clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE); @@ -1130,7 +1133,7 @@ int bitmap_daemon_work(struct bitmap *bitmap) spin_unlock_irqrestore(&bitmap->lock, flags); } - put_page(lastpage); + page_cache_release(lastpage); } return err; @@ -1181,7 +1184,7 @@ static void bitmap_writeback_daemon(mddev_t *mddev) PRINTK("finished page writeback: %p\n", page); err = PageError(page); - put_page(page); + page_cache_release(page); if (err) { printk(KERN_WARNING "%s: bitmap file writeback " "failed (page %lu): %d\n", @@ -1527,8 +1530,6 @@ void bitmap_destroy(mddev_t *mddev) return; mddev->bitmap = NULL; /* disconnect from the md device */ - if (mddev->thread) - mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; bitmap_free(bitmap); } @@ -1554,10 +1555,12 @@ int bitmap_create(mddev_t *mddev) BUG_ON(file && mddev->bitmap_offset); - bitmap = kzalloc(sizeof(*bitmap), GFP_KERNEL); + bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL); if (!bitmap) return -ENOMEM; + memset(bitmap, 0, sizeof(*bitmap)); + spin_lock_init(&bitmap->lock); bitmap->mddev = mddev; @@ -1598,11 +1601,12 @@ int bitmap_create(mddev_t *mddev) #ifdef INJECT_FATAL_FAULT_1 bitmap->bp = NULL; #else - bitmap->bp = kzalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL); + bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL); #endif err = -ENOMEM; if (!bitmap->bp) goto error; + memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp)); bitmap->flags |= BITMAP_ACTIVE; @@ -1632,8 +1636,6 @@ int bitmap_create(mddev_t *mddev) if (IS_ERR(bitmap->writeback_daemon)) return PTR_ERR(bitmap->writeback_daemon); - mddev->thread->timeout = bitmap->daemon_sleep * HZ; - return bitmap_update_sb(bitmap); error: diff --git a/trunk/drivers/md/dm-crypt.c b/trunk/drivers/md/dm-crypt.c index a601a427885c..cf6631056683 100644 --- a/trunk/drivers/md/dm-crypt.c +++ b/trunk/drivers/md/dm-crypt.c @@ -690,8 +690,6 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) bad2: crypto_free_tfm(tfm); bad1: - /* Must zero key material before freeing */ - memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8)); kfree(cc); return -EINVAL; } @@ -708,9 +706,6 @@ static void crypt_dtr(struct dm_target *ti) cc->iv_gen_ops->dtr(cc); crypto_free_tfm(cc->tfm); dm_put_device(ti, cc->dev); - - /* Must zero key material before freeing */ - memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8)); kfree(cc); } diff --git a/trunk/drivers/md/dm-io.h b/trunk/drivers/md/dm-io.h index f9035bfd1a9f..1a77f3265706 100644 --- a/trunk/drivers/md/dm-io.h +++ b/trunk/drivers/md/dm-io.h @@ -9,6 +9,9 @@ #include "dm.h" +/* FIXME make this configurable */ +#define DM_MAX_IO_REGIONS 8 + struct io_region { struct block_device *bdev; sector_t sector; diff --git a/trunk/drivers/md/dm-ioctl.c b/trunk/drivers/md/dm-ioctl.c index 561bda5011e0..07d44e19536e 100644 --- a/trunk/drivers/md/dm-ioctl.c +++ b/trunk/drivers/md/dm-ioctl.c @@ -270,7 +270,6 @@ static int dm_hash_rename(const char *old, const char *new) { char *new_name, *old_name; struct hash_cell *hc; - struct dm_table *table; /* * duplicate new. @@ -318,15 +317,6 @@ static int dm_hash_rename(const char *old, const char *new) /* rename the device node in devfs */ register_with_devfs(hc); - /* - * Wake up any dm event waiters. - */ - table = dm_get_table(hc->md); - if (table) { - dm_table_event(table); - dm_table_put(table); - } - up_write(&_hash_lock); kfree(old_name); return 0; @@ -693,18 +683,14 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) static int do_suspend(struct dm_ioctl *param) { int r = 0; - int do_lockfs = 1; struct mapped_device *md; md = find_device(param); if (!md) return -ENXIO; - if (param->flags & DM_SKIP_LOCKFS_FLAG) - do_lockfs = 0; - if (!dm_suspended(md)) - r = dm_suspend(md, do_lockfs); + r = dm_suspend(md); if (!r) r = __dev_status(md, param); @@ -716,7 +702,6 @@ static int do_suspend(struct dm_ioctl *param) static int do_resume(struct dm_ioctl *param) { int r = 0; - int do_lockfs = 1; struct hash_cell *hc; struct mapped_device *md; struct dm_table *new_map; @@ -742,10 +727,8 @@ static int do_resume(struct dm_ioctl *param) /* Do we need to load a new map ? */ if (new_map) { /* Suspend if it isn't already suspended */ - if (param->flags & DM_SKIP_LOCKFS_FLAG) - do_lockfs = 0; if (!dm_suspended(md)) - dm_suspend(md, do_lockfs); + dm_suspend(md); r = dm_swap_table(md, new_map); if (r) { diff --git a/trunk/drivers/md/dm-log.c b/trunk/drivers/md/dm-log.c index efe4adf78530..a76349cb10a5 100644 --- a/trunk/drivers/md/dm-log.c +++ b/trunk/drivers/md/dm-log.c @@ -573,7 +573,7 @@ static int core_get_resync_work(struct dirty_log *log, region_t *region) lc->sync_search); lc->sync_search = *region + 1; - if (*region >= lc->region_count) + if (*region == lc->region_count) return 0; } while (log_test_bit(lc->recovering_bits, *region)); diff --git a/trunk/drivers/md/dm-raid1.c b/trunk/drivers/md/dm-raid1.c index 6cfa8d435d55..6b0fc1670929 100644 --- a/trunk/drivers/md/dm-raid1.c +++ b/trunk/drivers/md/dm-raid1.c @@ -562,8 +562,6 @@ struct mirror_set { region_t nr_regions; int in_sync; - struct mirror *default_mirror; /* Default mirror */ - unsigned int nr_mirrors; struct mirror mirror[0]; }; @@ -613,7 +611,7 @@ static int recover(struct mirror_set *ms, struct region *reg) unsigned long flags = 0; /* fill in the source */ - m = ms->default_mirror; + m = ms->mirror + DEFAULT_MIRROR; from.bdev = m->dev->bdev; from.sector = m->offset + region_to_sector(reg->rh, reg->key); if (reg->key == (ms->nr_regions - 1)) { @@ -629,7 +627,7 @@ static int recover(struct mirror_set *ms, struct region *reg) /* fill in the destinations */ for (i = 0, dest = to; i < ms->nr_mirrors; i++) { - if (&ms->mirror[i] == ms->default_mirror) + if (i == DEFAULT_MIRROR) continue; m = ms->mirror + i; @@ -684,7 +682,7 @@ static void do_recovery(struct mirror_set *ms) static struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector) { /* FIXME: add read balancing */ - return ms->default_mirror; + return ms->mirror + DEFAULT_MIRROR; } /* @@ -711,7 +709,7 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads) if (rh_in_sync(&ms->rh, region, 0)) m = choose_mirror(ms, bio->bi_sector); else - m = ms->default_mirror; + m = ms->mirror + DEFAULT_MIRROR; map_bio(ms, m, bio); generic_make_request(bio); @@ -835,7 +833,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) rh_delay(&ms->rh, bio); while ((bio = bio_list_pop(&nosync))) { - map_bio(ms, ms->default_mirror, bio); + map_bio(ms, ms->mirror + DEFAULT_MIRROR, bio); generic_make_request(bio); } } @@ -902,7 +900,6 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors, ms->nr_mirrors = nr_mirrors; ms->nr_regions = dm_sector_div_up(ti->len, region_size); ms->in_sync = 0; - ms->default_mirror = &ms->mirror[DEFAULT_MIRROR]; if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) { ti->error = "dm-mirror: Error creating dirty region hash"; diff --git a/trunk/drivers/md/dm-snap.c b/trunk/drivers/md/dm-snap.c index 4b9dd8fb1e5c..ab54f99b7c3b 100644 --- a/trunk/drivers/md/dm-snap.c +++ b/trunk/drivers/md/dm-snap.c @@ -371,20 +371,6 @@ static inline ulong round_up(ulong n, ulong size) return (n + size) & ~size; } -static void read_snapshot_metadata(struct dm_snapshot *s) -{ - if (s->have_metadata) - return; - - if (s->store.read_metadata(&s->store)) { - down_write(&s->lock); - s->valid = 0; - up_write(&s->lock); - } - - s->have_metadata = 1; -} - /* * Construct a snapshot mapping:

*/ @@ -862,7 +848,16 @@ static void snapshot_resume(struct dm_target *ti) { struct dm_snapshot *s = (struct dm_snapshot *) ti->private; - read_snapshot_metadata(s); + if (s->have_metadata) + return; + + if (s->store.read_metadata(&s->store)) { + down_write(&s->lock); + s->valid = 0; + up_write(&s->lock); + } + + s->have_metadata = 1; } static int snapshot_status(struct dm_target *ti, status_type_t type, diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index 0e481512f918..930b9fc27953 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -55,7 +55,6 @@ union map_info *dm_get_mapinfo(struct bio *bio) */ #define DMF_BLOCK_IO 0 #define DMF_SUSPENDED 1 -#define DMF_FROZEN 2 struct mapped_device { struct rw_semaphore io_lock; @@ -98,7 +97,7 @@ struct mapped_device { * freeze/thaw support require holding onto a super block */ struct super_block *frozen_sb; - struct block_device *suspended_bdev; + struct block_device *frozen_bdev; }; #define MIN_IOS 256 @@ -837,9 +836,9 @@ static void __set_size(struct mapped_device *md, sector_t size) { set_capacity(md->disk, size); - down(&md->suspended_bdev->bd_inode->i_sem); - i_size_write(md->suspended_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); - up(&md->suspended_bdev->bd_inode->i_sem); + down(&md->frozen_bdev->bd_inode->i_sem); + i_size_write(md->frozen_bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); + up(&md->frozen_bdev->bd_inode->i_sem); } static int __bind(struct mapped_device *md, struct dm_table *t) @@ -903,9 +902,10 @@ int dm_create_with_minor(unsigned int minor, struct mapped_device **result) return create_aux(minor, 1, result); } -static struct mapped_device *dm_find_md(dev_t dev) +void *dm_get_mdptr(dev_t dev) { struct mapped_device *md; + void *mdptr = NULL; unsigned minor = MINOR(dev); if (MAJOR(dev) != _major || minor >= (1 << MINORBITS)) @@ -914,32 +914,12 @@ static struct mapped_device *dm_find_md(dev_t dev) down(&_minor_lock); md = idr_find(&_minor_idr, minor); - if (!md || (dm_disk(md)->first_minor != minor)) - md = NULL; - - up(&_minor_lock); - - return md; -} - -struct mapped_device *dm_get_md(dev_t dev) -{ - struct mapped_device *md = dm_find_md(dev); - - if (md) - dm_get(md); - return md; -} + if (md && (dm_disk(md)->first_minor == minor)) + mdptr = md->interface_ptr; -void *dm_get_mdptr(dev_t dev) -{ - struct mapped_device *md; - void *mdptr = NULL; + up(&_minor_lock); - md = dm_find_md(dev); - if (md) - mdptr = md->interface_ptr; return mdptr; } @@ -1011,33 +991,43 @@ int dm_swap_table(struct mapped_device *md, struct dm_table *table) */ static int lock_fs(struct mapped_device *md) { - int r; + int r = -ENOMEM; + + md->frozen_bdev = bdget_disk(md->disk, 0); + if (!md->frozen_bdev) { + DMWARN("bdget failed in lock_fs"); + goto out; + } WARN_ON(md->frozen_sb); - md->frozen_sb = freeze_bdev(md->suspended_bdev); + md->frozen_sb = freeze_bdev(md->frozen_bdev); if (IS_ERR(md->frozen_sb)) { r = PTR_ERR(md->frozen_sb); - md->frozen_sb = NULL; - return r; + goto out_bdput; } - set_bit(DMF_FROZEN, &md->flags); - /* don't bdput right now, we don't want the bdev - * to go away while it is locked. + * to go away while it is locked. We'll bdput + * in unlock_fs */ return 0; + +out_bdput: + bdput(md->frozen_bdev); + md->frozen_sb = NULL; + md->frozen_bdev = NULL; +out: + return r; } static void unlock_fs(struct mapped_device *md) { - if (!test_bit(DMF_FROZEN, &md->flags)) - return; + thaw_bdev(md->frozen_bdev, md->frozen_sb); + bdput(md->frozen_bdev); - thaw_bdev(md->suspended_bdev, md->frozen_sb); md->frozen_sb = NULL; - clear_bit(DMF_FROZEN, &md->flags); + md->frozen_bdev = NULL; } /* @@ -1047,7 +1037,7 @@ static void unlock_fs(struct mapped_device *md) * dm_bind_table, dm_suspend must be called to flush any in * flight bios and ensure that any further io gets deferred. */ -int dm_suspend(struct mapped_device *md, int do_lockfs) +int dm_suspend(struct mapped_device *md) { struct dm_table *map = NULL; DECLARE_WAITQUEUE(wait, current); @@ -1063,19 +1053,10 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) /* This does not get reverted if there's an error later. */ dm_table_presuspend_targets(map); - md->suspended_bdev = bdget_disk(md->disk, 0); - if (!md->suspended_bdev) { - DMWARN("bdget failed in dm_suspend"); - r = -ENOMEM; - goto out; - } - /* Flush I/O to the device. */ - if (do_lockfs) { - r = lock_fs(md); - if (r) - goto out; - } + r = lock_fs(md); + if (r) + goto out; /* * First we set the BLOCK_IO flag so no more ios will be mapped. @@ -1124,11 +1105,6 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) r = 0; out: - if (r && md->suspended_bdev) { - bdput(md->suspended_bdev); - md->suspended_bdev = NULL; - } - dm_table_put(map); up(&md->suspend_lock); return r; @@ -1159,9 +1135,6 @@ int dm_resume(struct mapped_device *md) unlock_fs(md); - bdput(md->suspended_bdev); - md->suspended_bdev = NULL; - clear_bit(DMF_SUSPENDED, &md->flags); dm_table_unplug_all(map); diff --git a/trunk/drivers/md/dm.h b/trunk/drivers/md/dm.h index 4eaf075da217..e38c3fc1a1db 100644 --- a/trunk/drivers/md/dm.h +++ b/trunk/drivers/md/dm.h @@ -28,7 +28,7 @@ * in types.h. */ #ifdef CONFIG_LBD -#define SECTOR_FORMAT "%llu" +#define SECTOR_FORMAT "%Lu" #else #define SECTOR_FORMAT "%lu" #endif @@ -58,7 +58,6 @@ int dm_create(struct mapped_device **md); int dm_create_with_minor(unsigned int minor, struct mapped_device **md); void dm_set_mdptr(struct mapped_device *md, void *ptr); void *dm_get_mdptr(dev_t dev); -struct mapped_device *dm_get_md(dev_t dev); /* * Reference counting for md. @@ -69,7 +68,7 @@ void dm_put(struct mapped_device *md); /* * A device can still be used while suspended, but I/O is deferred. */ -int dm_suspend(struct mapped_device *md, int with_lockfs); +int dm_suspend(struct mapped_device *md); int dm_resume(struct mapped_device *md); /* diff --git a/trunk/drivers/md/faulty.c b/trunk/drivers/md/faulty.c index a7a5ab554338..0248f8e7eac0 100644 --- a/trunk/drivers/md/faulty.c +++ b/trunk/drivers/md/faulty.c @@ -316,10 +316,9 @@ static int stop(mddev_t *mddev) return 0; } -static struct mdk_personality faulty_personality = +static mdk_personality_t faulty_personality = { .name = "faulty", - .level = LEVEL_FAULTY, .owner = THIS_MODULE, .make_request = make_request, .run = run, @@ -330,17 +329,15 @@ static struct mdk_personality faulty_personality = static int __init raid_init(void) { - return register_md_personality(&faulty_personality); + return register_md_personality(FAULTY, &faulty_personality); } static void raid_exit(void) { - unregister_md_personality(&faulty_personality); + unregister_md_personality(FAULTY); } module_init(raid_init); module_exit(raid_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS("md-personality-10"); /* faulty */ -MODULE_ALIAS("md-faulty"); -MODULE_ALIAS("md-level--5"); diff --git a/trunk/drivers/md/kcopyd.c b/trunk/drivers/md/kcopyd.c index ca99979c868a..eb7036485975 100644 --- a/trunk/drivers/md/kcopyd.c +++ b/trunk/drivers/md/kcopyd.c @@ -561,13 +561,11 @@ int kcopyd_copy(struct kcopyd_client *kc, struct io_region *from, * Cancels a kcopyd job, eg. someone might be deactivating a * mirror. */ -#if 0 int kcopyd_cancel(struct kcopyd_job *job, int block) { /* FIXME: finish */ return -1; } -#endif /* 0 */ /*----------------------------------------------------------------- * Unit setup @@ -686,3 +684,4 @@ void kcopyd_client_destroy(struct kcopyd_client *kc) EXPORT_SYMBOL(kcopyd_client_create); EXPORT_SYMBOL(kcopyd_client_destroy); EXPORT_SYMBOL(kcopyd_copy); +EXPORT_SYMBOL(kcopyd_cancel); diff --git a/trunk/drivers/md/linear.c b/trunk/drivers/md/linear.c index 777585458c85..946efef3a8f5 100644 --- a/trunk/drivers/md/linear.c +++ b/trunk/drivers/md/linear.c @@ -121,10 +121,11 @@ static int linear_run (mddev_t *mddev) sector_t curr_offset; struct list_head *tmp; - conf = kzalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t), + conf = kmalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t), GFP_KERNEL); if (!conf) goto out; + memset(conf, 0, sizeof(*conf) + mddev->raid_disks*sizeof(dev_info_t)); mddev->private = conf; cnt = 0; @@ -351,10 +352,9 @@ static void linear_status (struct seq_file *seq, mddev_t *mddev) } -static struct mdk_personality linear_personality = +static mdk_personality_t linear_personality= { .name = "linear", - .level = LEVEL_LINEAR, .owner = THIS_MODULE, .make_request = linear_make_request, .run = linear_run, @@ -364,18 +364,16 @@ static struct mdk_personality linear_personality = static int __init linear_init (void) { - return register_md_personality (&linear_personality); + return register_md_personality (LINEAR, &linear_personality); } static void linear_exit (void) { - unregister_md_personality (&linear_personality); + unregister_md_personality (LINEAR); } module_init(linear_init); module_exit(linear_exit); MODULE_LICENSE("GPL"); -MODULE_ALIAS("md-personality-1"); /* LINEAR - deprecated*/ -MODULE_ALIAS("md-linear"); -MODULE_ALIAS("md-level--1"); +MODULE_ALIAS("md-personality-1"); /* LINEAR */ diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 1b76fb29fb70..8175a2a222da 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -42,7 +42,6 @@ #include #include /* for invalidate_bdev */ #include -#include #include @@ -68,7 +67,7 @@ static void autostart_arrays (int part); #endif -static LIST_HEAD(pers_list); +static mdk_personality_t *pers[MAX_PERSONALITY]; static DEFINE_SPINLOCK(pers_lock); /* @@ -81,22 +80,10 @@ static DEFINE_SPINLOCK(pers_lock); * idle IO detection. * * you can change it via /proc/sys/dev/raid/speed_limit_min and _max. - * or /sys/block/mdX/md/sync_speed_{min,max} */ static int sysctl_speed_limit_min = 1000; static int sysctl_speed_limit_max = 200000; -static inline int speed_min(mddev_t *mddev) -{ - return mddev->sync_speed_min ? - mddev->sync_speed_min : sysctl_speed_limit_min; -} - -static inline int speed_max(mddev_t *mddev) -{ - return mddev->sync_speed_max ? - mddev->sync_speed_max : sysctl_speed_limit_max; -} static struct ctl_table_header *raid_table_header; @@ -146,24 +133,6 @@ static struct block_device_operations md_fops; static int start_readonly; -/* - * We have a system wide 'event count' that is incremented - * on any 'interesting' event, and readers of /proc/mdstat - * can use 'poll' or 'select' to find out when the event - * count increases. - * - * Events are: - * start array, stop array, error, add device, remove device, - * start build, activate spare - */ -static DECLARE_WAIT_QUEUE_HEAD(md_event_waiters); -static atomic_t md_event_count; -static void md_new_event(mddev_t *mddev) -{ - atomic_inc(&md_event_count); - wake_up(&md_event_waiters); -} - /* * Enables to iterate over all existing md arrays * all_mddevs_lock protects this list. @@ -240,10 +209,12 @@ static mddev_t * mddev_find(dev_t unit) } spin_unlock(&all_mddevs_lock); - new = kzalloc(sizeof(*new), GFP_KERNEL); + new = (mddev_t *) kmalloc(sizeof(*new), GFP_KERNEL); if (!new) return NULL; + memset(new, 0, sizeof(*new)); + new->unit = unit; if (MAJOR(unit) == MD_MAJOR) new->md_minor = MINOR(unit); @@ -291,7 +262,7 @@ static inline void mddev_unlock(mddev_t * mddev) md_wakeup_thread(mddev->thread); } -static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) +mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) { mdk_rdev_t * rdev; struct list_head *tmp; @@ -315,18 +286,6 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev) return NULL; } -static struct mdk_personality *find_pers(int level, char *clevel) -{ - struct mdk_personality *pers; - list_for_each_entry(pers, &pers_list, list) { - if (level != LEVEL_NONE && pers->level == level) - return pers; - if (strcmp(pers->name, clevel)==0) - return pers; - } - return NULL; -} - static inline sector_t calc_dev_sboffset(struct block_device *bdev) { sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; @@ -361,7 +320,7 @@ static int alloc_disk_sb(mdk_rdev_t * rdev) static void free_disk_sb(mdk_rdev_t * rdev) { if (rdev->sb_page) { - put_page(rdev->sb_page); + page_cache_release(rdev->sb_page); rdev->sb_loaded = 0; rdev->sb_page = NULL; rdev->sb_offset = 0; @@ -502,7 +461,6 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size, bio_put(bio); return ret; } -EXPORT_SYMBOL_GPL(sync_page_io); static int read_disk_sb(mdk_rdev_t * rdev, int size) { @@ -707,10 +665,6 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version } rdev->size = calc_dev_size(rdev, sb->chunk_size); - if (rdev->size < sb->size && sb->level > 1) - /* "this cannot possibly happen" ... */ - ret = -EINVAL; - abort: return ret; } @@ -734,7 +688,6 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->ctime = sb->ctime; mddev->utime = sb->utime; mddev->level = sb->level; - mddev->clevel[0] = 0; mddev->layout = sb->layout; mddev->raid_disks = sb->raid_disks; mddev->size = sb->size; @@ -761,10 +714,9 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) if (sb->state & (1<bitmap_file == NULL) { - if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6 - && mddev->level != 10) { + if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6) { /* FIXME use a better test */ - printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); + printk(KERN_WARNING "md: bitmaps only support for raid1\n"); return -EINVAL; } mddev->bitmap_offset = mddev->default_bitmap_offset; @@ -1016,7 +968,6 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) } rdev->preferred_minor = 0xffff; rdev->data_offset = le64_to_cpu(sb->data_offset); - atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256; bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1; @@ -1055,9 +1006,6 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) rdev->size = le64_to_cpu(sb->data_size)/2; if (le32_to_cpu(sb->chunksize)) rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1); - - if (le32_to_cpu(sb->size) > rdev->size*2) - return -EINVAL; return 0; } @@ -1075,7 +1023,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1); mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1); mddev->level = le32_to_cpu(sb->level); - mddev->clevel[0] = 0; mddev->layout = le32_to_cpu(sb->layout); mddev->raid_disks = le32_to_cpu(sb->raid_disks); mddev->size = le64_to_cpu(sb->size)/2; @@ -1090,9 +1037,8 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET) && mddev->bitmap_file == NULL ) { - if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6 - && mddev->level != 10) { - printk(KERN_WARNING "md: bitmaps not supported for this level.\n"); + if (mddev->level != 1) { + printk(KERN_WARNING "md: bitmaps only supported for raid1\n"); return -EINVAL; } mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset); @@ -1159,8 +1105,6 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) else sb->resync_offset = cpu_to_le64(0); - sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors); - if (mddev->bitmap && mddev->bitmap_file == NULL) { sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset); sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET); @@ -1243,14 +1187,6 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) MD_BUG(); return -EINVAL; } - /* make sure rdev->size exceeds mddev->size */ - if (rdev->size && (mddev->size == 0 || rdev->size < mddev->size)) { - if (mddev->pers) - /* Cannot change size, so fail */ - return -ENOSPC; - else - mddev->size = rdev->size; - } same_pdev = match_dev_unit(mddev, rdev); if (same_pdev) printk(KERN_WARNING @@ -1560,26 +1496,6 @@ static void md_update_sb(mddev_t * mddev) } -/* words written to sysfs files may, or my not, be \n terminated. - * We want to accept with case. For this we use cmd_match. - */ -static int cmd_match(const char *cmd, const char *str) -{ - /* See if cmd, written into a sysfs file, matches - * str. They must either be the same, or cmd can - * have a trailing newline - */ - while (*cmd && *str && *cmd == *str) { - cmd++; - str++; - } - if (*cmd == '\n') - cmd++; - if (*str || *cmd) - return 0; - return 1; -} - struct rdev_sysfs_entry { struct attribute attr; ssize_t (*show)(mdk_rdev_t *, char *); @@ -1622,113 +1538,9 @@ super_show(mdk_rdev_t *rdev, char *page) } static struct rdev_sysfs_entry rdev_super = __ATTR_RO(super); -static ssize_t -errors_show(mdk_rdev_t *rdev, char *page) -{ - return sprintf(page, "%d\n", atomic_read(&rdev->corrected_errors)); -} - -static ssize_t -errors_store(mdk_rdev_t *rdev, const char *buf, size_t len) -{ - char *e; - unsigned long n = simple_strtoul(buf, &e, 10); - if (*buf && (*e == 0 || *e == '\n')) { - atomic_set(&rdev->corrected_errors, n); - return len; - } - return -EINVAL; -} -static struct rdev_sysfs_entry rdev_errors = -__ATTR(errors, 0644, errors_show, errors_store); - -static ssize_t -slot_show(mdk_rdev_t *rdev, char *page) -{ - if (rdev->raid_disk < 0) - return sprintf(page, "none\n"); - else - return sprintf(page, "%d\n", rdev->raid_disk); -} - -static ssize_t -slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) -{ - char *e; - int slot = simple_strtoul(buf, &e, 10); - if (strncmp(buf, "none", 4)==0) - slot = -1; - else if (e==buf || (*e && *e!= '\n')) - return -EINVAL; - if (rdev->mddev->pers) - /* Cannot set slot in active array (yet) */ - return -EBUSY; - if (slot >= rdev->mddev->raid_disks) - return -ENOSPC; - rdev->raid_disk = slot; - /* assume it is working */ - rdev->flags = 0; - set_bit(In_sync, &rdev->flags); - return len; -} - - -static struct rdev_sysfs_entry rdev_slot = -__ATTR(slot, 0644, slot_show, slot_store); - -static ssize_t -offset_show(mdk_rdev_t *rdev, char *page) -{ - return sprintf(page, "%llu\n", (unsigned long long)rdev->data_offset); -} - -static ssize_t -offset_store(mdk_rdev_t *rdev, const char *buf, size_t len) -{ - char *e; - unsigned long long offset = simple_strtoull(buf, &e, 10); - if (e==buf || (*e && *e != '\n')) - return -EINVAL; - if (rdev->mddev->pers) - return -EBUSY; - rdev->data_offset = offset; - return len; -} - -static struct rdev_sysfs_entry rdev_offset = -__ATTR(offset, 0644, offset_show, offset_store); - -static ssize_t -rdev_size_show(mdk_rdev_t *rdev, char *page) -{ - return sprintf(page, "%llu\n", (unsigned long long)rdev->size); -} - -static ssize_t -rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) -{ - char *e; - unsigned long long size = simple_strtoull(buf, &e, 10); - if (e==buf || (*e && *e != '\n')) - return -EINVAL; - if (rdev->mddev->pers) - return -EBUSY; - rdev->size = size; - if (size < rdev->mddev->size || rdev->mddev->size == 0) - rdev->mddev->size = size; - return len; -} - -static struct rdev_sysfs_entry rdev_size = -__ATTR(size, 0644, rdev_size_show, rdev_size_store); - static struct attribute *rdev_default_attrs[] = { &rdev_state.attr, &rdev_super.attr, - &rdev_errors.attr, - &rdev_slot.attr, - &rdev_offset.attr, - &rdev_size.attr, NULL, }; static ssize_t @@ -1786,11 +1598,12 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi mdk_rdev_t *rdev; sector_t size; - rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); + rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL); if (!rdev) { printk(KERN_ERR "md: could not alloc mem for new device!\n"); return ERR_PTR(-ENOMEM); } + memset(rdev, 0, sizeof(*rdev)); if ((err = alloc_disk_sb(rdev))) goto abort_free; @@ -1808,7 +1621,6 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi rdev->data_offset = 0; atomic_set(&rdev->nr_pending, 0); atomic_set(&rdev->read_errors, 0); - atomic_set(&rdev->corrected_errors, 0); size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; if (!size) { @@ -1913,37 +1725,16 @@ static void analyze_sbs(mddev_t * mddev) static ssize_t level_show(mddev_t *mddev, char *page) { - struct mdk_personality *p = mddev->pers; - if (p) - return sprintf(page, "%s\n", p->name); - else if (mddev->clevel[0]) - return sprintf(page, "%s\n", mddev->clevel); - else if (mddev->level != LEVEL_NONE) - return sprintf(page, "%d\n", mddev->level); - else + mdk_personality_t *p = mddev->pers; + if (p == NULL && mddev->raid_disks == 0) return 0; + if (mddev->level >= 0) + return sprintf(page, "raid%d\n", mddev->level); + else + return sprintf(page, "%s\n", p->name); } -static ssize_t -level_store(mddev_t *mddev, const char *buf, size_t len) -{ - int rv = len; - if (mddev->pers) - return -EBUSY; - if (len == 0) - return 0; - if (len >= sizeof(mddev->clevel)) - return -ENOSPC; - strncpy(mddev->clevel, buf, len); - if (mddev->clevel[len-1] == '\n') - len--; - mddev->clevel[len] = 0; - mddev->level = LEVEL_NONE; - return rv; -} - -static struct md_sysfs_entry md_level = -__ATTR(level, 0644, level_show, level_store); +static struct md_sysfs_entry md_level = __ATTR_RO(level); static ssize_t raid_disks_show(mddev_t *mddev, char *page) @@ -1953,197 +1744,7 @@ raid_disks_show(mddev_t *mddev, char *page) return sprintf(page, "%d\n", mddev->raid_disks); } -static int update_raid_disks(mddev_t *mddev, int raid_disks); - -static ssize_t -raid_disks_store(mddev_t *mddev, const char *buf, size_t len) -{ - /* can only set raid_disks if array is not yet active */ - char *e; - int rv = 0; - unsigned long n = simple_strtoul(buf, &e, 10); - - if (!*buf || (*e && *e != '\n')) - return -EINVAL; - - if (mddev->pers) - rv = update_raid_disks(mddev, n); - else - mddev->raid_disks = n; - return rv ? rv : len; -} -static struct md_sysfs_entry md_raid_disks = -__ATTR(raid_disks, 0644, raid_disks_show, raid_disks_store); - -static ssize_t -chunk_size_show(mddev_t *mddev, char *page) -{ - return sprintf(page, "%d\n", mddev->chunk_size); -} - -static ssize_t -chunk_size_store(mddev_t *mddev, const char *buf, size_t len) -{ - /* can only set chunk_size if array is not yet active */ - char *e; - unsigned long n = simple_strtoul(buf, &e, 10); - - if (mddev->pers) - return -EBUSY; - if (!*buf || (*e && *e != '\n')) - return -EINVAL; - - mddev->chunk_size = n; - return len; -} -static struct md_sysfs_entry md_chunk_size = -__ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store); - -static ssize_t -null_show(mddev_t *mddev, char *page) -{ - return -EINVAL; -} - -static ssize_t -new_dev_store(mddev_t *mddev, const char *buf, size_t len) -{ - /* buf must be %d:%d\n? giving major and minor numbers */ - /* The new device is added to the array. - * If the array has a persistent superblock, we read the - * superblock to initialise info and check validity. - * Otherwise, only checking done is that in bind_rdev_to_array, - * which mainly checks size. - */ - char *e; - int major = simple_strtoul(buf, &e, 10); - int minor; - dev_t dev; - mdk_rdev_t *rdev; - int err; - - if (!*buf || *e != ':' || !e[1] || e[1] == '\n') - return -EINVAL; - minor = simple_strtoul(e+1, &e, 10); - if (*e && *e != '\n') - return -EINVAL; - dev = MKDEV(major, minor); - if (major != MAJOR(dev) || - minor != MINOR(dev)) - return -EOVERFLOW; - - - if (mddev->persistent) { - rdev = md_import_device(dev, mddev->major_version, - mddev->minor_version); - if (!IS_ERR(rdev) && !list_empty(&mddev->disks)) { - mdk_rdev_t *rdev0 = list_entry(mddev->disks.next, - mdk_rdev_t, same_set); - err = super_types[mddev->major_version] - .load_super(rdev, rdev0, mddev->minor_version); - if (err < 0) - goto out; - } - } else - rdev = md_import_device(dev, -1, -1); - - if (IS_ERR(rdev)) - return PTR_ERR(rdev); - err = bind_rdev_to_array(rdev, mddev); - out: - if (err) - export_rdev(rdev); - return err ? err : len; -} - -static struct md_sysfs_entry md_new_device = -__ATTR(new_dev, 0200, null_show, new_dev_store); - -static ssize_t -size_show(mddev_t *mddev, char *page) -{ - return sprintf(page, "%llu\n", (unsigned long long)mddev->size); -} - -static int update_size(mddev_t *mddev, unsigned long size); - -static ssize_t -size_store(mddev_t *mddev, const char *buf, size_t len) -{ - /* If array is inactive, we can reduce the component size, but - * not increase it (except from 0). - * If array is active, we can try an on-line resize - */ - char *e; - int err = 0; - unsigned long long size = simple_strtoull(buf, &e, 10); - if (!*buf || *buf == '\n' || - (*e && *e != '\n')) - return -EINVAL; - - if (mddev->pers) { - err = update_size(mddev, size); - md_update_sb(mddev); - } else { - if (mddev->size == 0 || - mddev->size > size) - mddev->size = size; - else - err = -ENOSPC; - } - return err ? err : len; -} - -static struct md_sysfs_entry md_size = -__ATTR(component_size, 0644, size_show, size_store); - - -/* Metdata version. - * This is either 'none' for arrays with externally managed metadata, - * or N.M for internally known formats - */ -static ssize_t -metadata_show(mddev_t *mddev, char *page) -{ - if (mddev->persistent) - return sprintf(page, "%d.%d\n", - mddev->major_version, mddev->minor_version); - else - return sprintf(page, "none\n"); -} - -static ssize_t -metadata_store(mddev_t *mddev, const char *buf, size_t len) -{ - int major, minor; - char *e; - if (!list_empty(&mddev->disks)) - return -EBUSY; - - if (cmd_match(buf, "none")) { - mddev->persistent = 0; - mddev->major_version = 0; - mddev->minor_version = 90; - return len; - } - major = simple_strtoul(buf, &e, 10); - if (e==buf || *e != '.') - return -EINVAL; - buf = e+1; - minor = simple_strtoul(buf, &e, 10); - if (e==buf || *e != '\n') - return -EINVAL; - if (major >= sizeof(super_types)/sizeof(super_types[0]) || - super_types[major].name == NULL) - return -ENOENT; - mddev->major_version = major; - mddev->minor_version = minor; - mddev->persistent = 1; - return len; -} - -static struct md_sysfs_entry md_metadata = -__ATTR(metadata_version, 0644, metadata_show, metadata_store); +static struct md_sysfs_entry md_raid_disks = __ATTR_RO(raid_disks); static ssize_t action_show(mddev_t *mddev, char *page) @@ -2170,27 +1771,31 @@ action_store(mddev_t *mddev, const char *page, size_t len) if (!mddev->pers || !mddev->pers->sync_request) return -EINVAL; - if (cmd_match(page, "idle")) { + if (strcmp(page, "idle")==0 || strcmp(page, "idle\n")==0) { if (mddev->sync_thread) { set_bit(MD_RECOVERY_INTR, &mddev->recovery); md_unregister_thread(mddev->sync_thread); mddev->sync_thread = NULL; mddev->recovery = 0; } - } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || - test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) + return len; + } + + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || + test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) return -EBUSY; - else if (cmd_match(page, "resync") || cmd_match(page, "recover")) + if (strcmp(page, "resync")==0 || strcmp(page, "resync\n")==0 || + strcmp(page, "recover")==0 || strcmp(page, "recover\n")==0) set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); else { - if (cmd_match(page, "check")) + if (strcmp(page, "check")==0 || strcmp(page, "check\n")==0) set_bit(MD_RECOVERY_CHECK, &mddev->recovery); - else if (cmd_match(page, "repair")) + else if (strcmp(page, "repair")!=0 && strcmp(page, "repair\n")!=0) return -EINVAL; set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); set_bit(MD_RECOVERY_SYNC, &mddev->recovery); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); } - set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); return len; } @@ -2209,107 +1814,15 @@ md_scan_mode = __ATTR(sync_action, S_IRUGO|S_IWUSR, action_show, action_store); static struct md_sysfs_entry md_mismatches = __ATTR_RO(mismatch_cnt); -static ssize_t -sync_min_show(mddev_t *mddev, char *page) -{ - return sprintf(page, "%d (%s)\n", speed_min(mddev), - mddev->sync_speed_min ? "local": "system"); -} - -static ssize_t -sync_min_store(mddev_t *mddev, const char *buf, size_t len) -{ - int min; - char *e; - if (strncmp(buf, "system", 6)==0) { - mddev->sync_speed_min = 0; - return len; - } - min = simple_strtoul(buf, &e, 10); - if (buf == e || (*e && *e != '\n') || min <= 0) - return -EINVAL; - mddev->sync_speed_min = min; - return len; -} - -static struct md_sysfs_entry md_sync_min = -__ATTR(sync_speed_min, S_IRUGO|S_IWUSR, sync_min_show, sync_min_store); - -static ssize_t -sync_max_show(mddev_t *mddev, char *page) -{ - return sprintf(page, "%d (%s)\n", speed_max(mddev), - mddev->sync_speed_max ? "local": "system"); -} - -static ssize_t -sync_max_store(mddev_t *mddev, const char *buf, size_t len) -{ - int max; - char *e; - if (strncmp(buf, "system", 6)==0) { - mddev->sync_speed_max = 0; - return len; - } - max = simple_strtoul(buf, &e, 10); - if (buf == e || (*e && *e != '\n') || max <= 0) - return -EINVAL; - mddev->sync_speed_max = max; - return len; -} - -static struct md_sysfs_entry md_sync_max = -__ATTR(sync_speed_max, S_IRUGO|S_IWUSR, sync_max_show, sync_max_store); - - -static ssize_t -sync_speed_show(mddev_t *mddev, char *page) -{ - unsigned long resync, dt, db; - resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active)); - dt = ((jiffies - mddev->resync_mark) / HZ); - if (!dt) dt++; - db = resync - (mddev->resync_mark_cnt); - return sprintf(page, "%ld\n", db/dt/2); /* K/sec */ -} - -static struct md_sysfs_entry -md_sync_speed = __ATTR_RO(sync_speed); - -static ssize_t -sync_completed_show(mddev_t *mddev, char *page) -{ - unsigned long max_blocks, resync; - - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) - max_blocks = mddev->resync_max_sectors; - else - max_blocks = mddev->size << 1; - - resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active)); - return sprintf(page, "%lu / %lu\n", resync, max_blocks); -} - -static struct md_sysfs_entry -md_sync_completed = __ATTR_RO(sync_completed); - static struct attribute *md_default_attrs[] = { &md_level.attr, &md_raid_disks.attr, - &md_chunk_size.attr, - &md_size.attr, - &md_metadata.attr, - &md_new_device.attr, NULL, }; static struct attribute *md_redundancy_attrs[] = { &md_scan_mode.attr, &md_mismatches.attr, - &md_sync_min.attr, - &md_sync_max.attr, - &md_sync_speed.attr, - &md_sync_completed.attr, NULL, }; static struct attribute_group md_redundancy_group = { @@ -2424,16 +1937,14 @@ static void md_safemode_timeout(unsigned long data) md_wakeup_thread(mddev->thread); } -static int start_dirty_degraded; static int do_md_run(mddev_t * mddev) { - int err; + int pnum, err; int chunk_size; struct list_head *tmp; mdk_rdev_t *rdev; struct gendisk *disk; - struct mdk_personality *pers; char b[BDEVNAME_SIZE]; if (list_empty(&mddev->disks)) @@ -2450,8 +1961,20 @@ static int do_md_run(mddev_t * mddev) analyze_sbs(mddev); chunk_size = mddev->chunk_size; + pnum = level_to_pers(mddev->level); - if (chunk_size) { + if ((pnum != MULTIPATH) && (pnum != RAID1)) { + if (!chunk_size) { + /* + * 'default chunksize' in the old md code used to + * be PAGE_SIZE, baaad. + * we abort here to be on the safe side. We don't + * want to continue the bad practice. + */ + printk(KERN_ERR + "no chunksize specified, see 'man raidtab'\n"); + return -EINVAL; + } if (chunk_size > MAX_CHUNK_SIZE) { printk(KERN_ERR "too big chunk_size: %d > %d\n", chunk_size, MAX_CHUNK_SIZE); @@ -2487,10 +2010,10 @@ static int do_md_run(mddev_t * mddev) } #ifdef CONFIG_KMOD - if (mddev->level != LEVEL_NONE) - request_module("md-level-%d", mddev->level); - else if (mddev->clevel[0]) - request_module("md-%s", mddev->clevel); + if (!pers[pnum]) + { + request_module("md-personality-%d", pnum); + } #endif /* @@ -2512,39 +2035,30 @@ static int do_md_run(mddev_t * mddev) return -ENOMEM; spin_lock(&pers_lock); - pers = find_pers(mddev->level, mddev->clevel); - if (!pers || !try_module_get(pers->owner)) { + if (!pers[pnum] || !try_module_get(pers[pnum]->owner)) { spin_unlock(&pers_lock); - if (mddev->level != LEVEL_NONE) - printk(KERN_WARNING "md: personality for level %d is not loaded!\n", - mddev->level); - else - printk(KERN_WARNING "md: personality for level %s is not loaded!\n", - mddev->clevel); + printk(KERN_WARNING "md: personality %d is not loaded!\n", + pnum); return -EINVAL; } - mddev->pers = pers; + + mddev->pers = pers[pnum]; spin_unlock(&pers_lock); - mddev->level = pers->level; - strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel)); mddev->recovery = 0; mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ mddev->barriers_work = 1; - mddev->ok_start_degraded = start_dirty_degraded; if (start_readonly) mddev->ro = 2; /* read-only, but switch on first write */ - err = mddev->pers->run(mddev); - if (!err && mddev->pers->sync_request) { - err = bitmap_create(mddev); - if (err) { - printk(KERN_ERR "%s: failed to create bitmap (%d)\n", - mdname(mddev), err); - mddev->pers->stop(mddev); - } - } + /* before we start the array running, initialise the bitmap */ + err = bitmap_create(mddev); + if (err) + printk(KERN_ERR "%s: failed to create bitmap (%d)\n", + mdname(mddev), err); + else + err = mddev->pers->run(mddev); if (err) { printk(KERN_ERR "md: pers->run() failed ...\n"); module_put(mddev->pers->owner); @@ -2590,7 +2104,6 @@ static int do_md_run(mddev_t * mddev) mddev->queue->make_request_fn = mddev->pers->make_request; mddev->changed = 1; - md_new_event(mddev); return 0; } @@ -2718,7 +2231,6 @@ static int do_md_stop(mddev_t * mddev, int ro) printk(KERN_INFO "md: %s switched to read-only mode.\n", mdname(mddev)); err = 0; - md_new_event(mddev); out: return err; } @@ -3156,6 +2668,12 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) if (info->state & (1<flags); + err = bind_rdev_to_array(rdev, mddev); + if (err) { + export_rdev(rdev); + return err; + } + if (!mddev->persistent) { printk(KERN_INFO "md: nonpersistent superblock ...\n"); rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; @@ -3163,11 +2681,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) rdev->sb_offset = calc_dev_sboffset(rdev->bdev); rdev->size = calc_dev_size(rdev, mddev->chunk_size); - err = bind_rdev_to_array(rdev, mddev); - if (err) { - export_rdev(rdev); - return err; - } + if (!mddev->size || (mddev->size > rdev->size)) + mddev->size = rdev->size; } return 0; @@ -3190,7 +2705,6 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev) kick_rdev_from_array(rdev); md_update_sb(mddev); - md_new_event(mddev); return 0; busy: @@ -3239,6 +2753,15 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) size = calc_dev_size(rdev, mddev->chunk_size); rdev->size = size; + if (size < mddev->size) { + printk(KERN_WARNING + "%s: disk size %llu blocks < array size %llu\n", + mdname(mddev), (unsigned long long)size, + (unsigned long long)mddev->size); + err = -ENOSPC; + goto abort_export; + } + if (test_bit(Faulty, &rdev->flags)) { printk(KERN_WARNING "md: can not hot-add faulty %s disk to %s!\n", @@ -3248,9 +2771,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) } clear_bit(In_sync, &rdev->flags); rdev->desc_nr = -1; - err = bind_rdev_to_array(rdev, mddev); - if (err) - goto abort_export; + bind_rdev_to_array(rdev, mddev); /* * The rest should better be atomic, we can have disk failures @@ -3274,7 +2795,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) */ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); - md_new_event(mddev); + return 0; abort_unbind_export: @@ -3421,81 +2942,6 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) return 0; } -static int update_size(mddev_t *mddev, unsigned long size) -{ - mdk_rdev_t * rdev; - int rv; - struct list_head *tmp; - - if (mddev->pers->resize == NULL) - return -EINVAL; - /* The "size" is the amount of each device that is used. - * This can only make sense for arrays with redundancy. - * linear and raid0 always use whatever space is available - * We can only consider changing the size if no resync - * or reconstruction is happening, and if the new size - * is acceptable. It must fit before the sb_offset or, - * if that is sync_thread) - return -EBUSY; - ITERATE_RDEV(mddev,rdev,tmp) { - sector_t avail; - int fit = (size == 0); - if (rdev->sb_offset > rdev->data_offset) - avail = (rdev->sb_offset*2) - rdev->data_offset; - else - avail = get_capacity(rdev->bdev->bd_disk) - - rdev->data_offset; - if (fit && (size == 0 || size > avail/2)) - size = avail/2; - if (avail < ((sector_t)size << 1)) - return -ENOSPC; - } - rv = mddev->pers->resize(mddev, (sector_t)size *2); - if (!rv) { - struct block_device *bdev; - - bdev = bdget_disk(mddev->gendisk, 0); - if (bdev) { - down(&bdev->bd_inode->i_sem); - i_size_write(bdev->bd_inode, mddev->array_size << 10); - up(&bdev->bd_inode->i_sem); - bdput(bdev); - } - } - return rv; -} - -static int update_raid_disks(mddev_t *mddev, int raid_disks) -{ - int rv; - /* change the number of raid disks */ - if (mddev->pers->reshape == NULL) - return -EINVAL; - if (raid_disks <= 0 || - raid_disks >= mddev->max_disks) - return -EINVAL; - if (mddev->sync_thread) - return -EBUSY; - rv = mddev->pers->reshape(mddev, raid_disks); - if (!rv) { - struct block_device *bdev; - - bdev = bdget_disk(mddev->gendisk, 0); - if (bdev) { - down(&bdev->bd_inode->i_sem); - i_size_write(bdev->bd_inode, mddev->array_size << 10); - up(&bdev->bd_inode->i_sem); - bdput(bdev); - } - } - return rv; -} - - /* * update_array_info is used to change the configuration of an * on-line array. @@ -3544,12 +2990,71 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info) else return mddev->pers->reconfig(mddev, info->layout, -1); } - if (mddev->size != info->size) - rv = update_size(mddev, info->size); - - if (mddev->raid_disks != info->raid_disks) - rv = update_raid_disks(mddev, info->raid_disks); - + if (mddev->size != info->size) { + mdk_rdev_t * rdev; + struct list_head *tmp; + if (mddev->pers->resize == NULL) + return -EINVAL; + /* The "size" is the amount of each device that is used. + * This can only make sense for arrays with redundancy. + * linear and raid0 always use whatever space is available + * We can only consider changing the size if no resync + * or reconstruction is happening, and if the new size + * is acceptable. It must fit before the sb_offset or, + * if that is sync_thread) + return -EBUSY; + ITERATE_RDEV(mddev,rdev,tmp) { + sector_t avail; + int fit = (info->size == 0); + if (rdev->sb_offset > rdev->data_offset) + avail = (rdev->sb_offset*2) - rdev->data_offset; + else + avail = get_capacity(rdev->bdev->bd_disk) + - rdev->data_offset; + if (fit && (info->size == 0 || info->size > avail/2)) + info->size = avail/2; + if (avail < ((sector_t)info->size << 1)) + return -ENOSPC; + } + rv = mddev->pers->resize(mddev, (sector_t)info->size *2); + if (!rv) { + struct block_device *bdev; + + bdev = bdget_disk(mddev->gendisk, 0); + if (bdev) { + down(&bdev->bd_inode->i_sem); + i_size_write(bdev->bd_inode, mddev->array_size << 10); + up(&bdev->bd_inode->i_sem); + bdput(bdev); + } + } + } + if (mddev->raid_disks != info->raid_disks) { + /* change the number of raid disks */ + if (mddev->pers->reshape == NULL) + return -EINVAL; + if (info->raid_disks <= 0 || + info->raid_disks >= mddev->max_disks) + return -EINVAL; + if (mddev->sync_thread) + return -EBUSY; + rv = mddev->pers->reshape(mddev, info->raid_disks); + if (!rv) { + struct block_device *bdev; + + bdev = bdget_disk(mddev->gendisk, 0); + if (bdev) { + down(&bdev->bd_inode->i_sem); + i_size_write(bdev->bd_inode, mddev->array_size << 10); + up(&bdev->bd_inode->i_sem); + bdput(bdev); + } + } + } if ((state ^ info->state) & (1<pers->quiesce == NULL) return -EINVAL; @@ -3971,10 +3476,11 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, { mdk_thread_t *thread; - thread = kzalloc(sizeof(mdk_thread_t), GFP_KERNEL); + thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL); if (!thread) return NULL; + memset(thread, 0, sizeof(mdk_thread_t)); init_waitqueue_head(&thread->wqueue); thread->run = run; @@ -4018,7 +3524,6 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev) set_bit(MD_RECOVERY_INTR, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); - md_new_event(mddev); } /* seq_file implementation /proc/mdstat */ @@ -4159,29 +3664,24 @@ static void md_seq_stop(struct seq_file *seq, void *v) mddev_put(mddev); } -struct mdstat_info { - int event; -}; - static int md_seq_show(struct seq_file *seq, void *v) { mddev_t *mddev = v; sector_t size; struct list_head *tmp2; mdk_rdev_t *rdev; - struct mdstat_info *mi = seq->private; + int i; struct bitmap *bitmap; if (v == (void*)1) { - struct mdk_personality *pers; seq_printf(seq, "Personalities : "); spin_lock(&pers_lock); - list_for_each_entry(pers, &pers_list, list) - seq_printf(seq, "[%s] ", pers->name); + for (i = 0; i < MAX_PERSONALITY; i++) + if (pers[i]) + seq_printf(seq, "[%s] ", pers[i]->name); spin_unlock(&pers_lock); seq_printf(seq, "\n"); - mi->event = atomic_read(&md_event_count); return 0; } if (v == (void*)2) { @@ -4290,68 +3790,47 @@ static struct seq_operations md_seq_ops = { static int md_seq_open(struct inode *inode, struct file *file) { int error; - struct mdstat_info *mi = kmalloc(sizeof(*mi), GFP_KERNEL); - if (mi == NULL) - return -ENOMEM; error = seq_open(file, &md_seq_ops); - if (error) - kfree(mi); - else { - struct seq_file *p = file->private_data; - p->private = mi; - mi->event = atomic_read(&md_event_count); - } return error; } -static int md_seq_release(struct inode *inode, struct file *file) -{ - struct seq_file *m = file->private_data; - struct mdstat_info *mi = m->private; - m->private = NULL; - kfree(mi); - return seq_release(inode, file); -} - -static unsigned int mdstat_poll(struct file *filp, poll_table *wait) -{ - struct seq_file *m = filp->private_data; - struct mdstat_info *mi = m->private; - int mask; - - poll_wait(filp, &md_event_waiters, wait); - - /* always allow read */ - mask = POLLIN | POLLRDNORM; - - if (mi->event != atomic_read(&md_event_count)) - mask |= POLLERR | POLLPRI; - return mask; -} - static struct file_operations md_seq_fops = { .open = md_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = md_seq_release, - .poll = mdstat_poll, + .release = seq_release, }; -int register_md_personality(struct mdk_personality *p) +int register_md_personality(int pnum, mdk_personality_t *p) { + if (pnum >= MAX_PERSONALITY) { + printk(KERN_ERR + "md: tried to install personality %s as nr %d, but max is %lu\n", + p->name, pnum, MAX_PERSONALITY-1); + return -EINVAL; + } + spin_lock(&pers_lock); - list_add_tail(&p->list, &pers_list); - printk(KERN_INFO "md: %s personality registered for level %d\n", p->name, p->level); + if (pers[pnum]) { + spin_unlock(&pers_lock); + return -EBUSY; + } + + pers[pnum] = p; + printk(KERN_INFO "md: %s personality registered as nr %d\n", p->name, pnum); spin_unlock(&pers_lock); return 0; } -int unregister_md_personality(struct mdk_personality *p) +int unregister_md_personality(int pnum) { - printk(KERN_INFO "md: %s personality unregistered\n", p->name); + if (pnum >= MAX_PERSONALITY) + return -EINVAL; + + printk(KERN_INFO "md: %s personality unregistered\n", pers[pnum]->name); spin_lock(&pers_lock); - list_del_init(&p->list); + pers[pnum] = NULL; spin_unlock(&pers_lock); return 0; } @@ -4533,10 +4012,10 @@ static void md_do_sync(mddev_t *mddev) printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev)); printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:" - " %d KB/sec/disc.\n", speed_min(mddev)); + " %d KB/sec/disc.\n", sysctl_speed_limit_min); printk(KERN_INFO "md: using maximum available idle IO bandwidth " "(but not more than %d KB/sec) for reconstruction.\n", - speed_max(mddev)); + sysctl_speed_limit_max); is_mddev_idle(mddev); /* this also initializes IO event counters */ /* we don't use the checkpoint if there's a bitmap */ @@ -4577,7 +4056,7 @@ static void md_do_sync(mddev_t *mddev) skipped = 0; sectors = mddev->pers->sync_request(mddev, j, &skipped, - currspeed < speed_min(mddev)); + currspeed < sysctl_speed_limit_min); if (sectors == 0) { set_bit(MD_RECOVERY_ERR, &mddev->recovery); goto out; @@ -4590,11 +4069,7 @@ static void md_do_sync(mddev_t *mddev) j += sectors; if (j>1) mddev->curr_resync = j; - if (last_check == 0) - /* this is the earliers that rebuilt will be - * visible in /proc/mdstat - */ - md_new_event(mddev); + if (last_check + window > io_sectors || j == max_sectors) continue; @@ -4642,8 +4117,8 @@ static void md_do_sync(mddev_t *mddev) currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2 /((jiffies-mddev->resync_mark)/HZ +1) +1; - if (currspeed > speed_min(mddev)) { - if ((currspeed > speed_max(mddev)) || + if (currspeed > sysctl_speed_limit_min) { + if ((currspeed > sysctl_speed_limit_max) || !is_mddev_idle(mddev)) { msleep(500); goto repeat; @@ -4780,7 +4255,6 @@ void md_check_recovery(mddev_t *mddev) mddev->recovery = 0; /* flag recovery needed just to double check */ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - md_new_event(mddev); goto unlock; } /* Clear some bits that don't mean anything, but @@ -4818,7 +4292,6 @@ void md_check_recovery(mddev_t *mddev) sprintf(nm, "rd%d", rdev->raid_disk); sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); spares++; - md_new_event(mddev); } else break; } @@ -4851,9 +4324,9 @@ void md_check_recovery(mddev_t *mddev) mdname(mddev)); /* leave the spares where they are, it shouldn't hurt */ mddev->recovery = 0; - } else + } else { md_wakeup_thread(mddev->sync_thread); - md_new_event(mddev); + } } unlock: mddev_unlock(mddev); @@ -5030,14 +4503,12 @@ static int set_ro(const char *val, struct kernel_param *kp) int num = simple_strtoul(val, &e, 10); if (*val && (*e == '\0' || *e == '\n')) { start_readonly = num; - return 0; + return 0;; } return -EINVAL; } module_param_call(start_ro, set_ro, get_ro, NULL, 0600); -module_param(start_dirty_degraded, int, 0644); - EXPORT_SYMBOL(register_md_personality); EXPORT_SYMBOL(unregister_md_personality); diff --git a/trunk/drivers/md/multipath.c b/trunk/drivers/md/multipath.c index e6aa309a66d7..145cdc5ad008 100644 --- a/trunk/drivers/md/multipath.c +++ b/trunk/drivers/md/multipath.c @@ -35,10 +35,15 @@ #define NR_RESERVED_BUFS 32 +static mdk_personality_t multipath_personality; + + static void *mp_pool_alloc(gfp_t gfp_flags, void *data) { struct multipath_bh *mpb; - mpb = kzalloc(sizeof(*mpb), gfp_flags); + mpb = kmalloc(sizeof(*mpb), gfp_flags); + if (mpb) + memset(mpb, 0, sizeof(*mpb)); return mpb; } @@ -439,7 +444,7 @@ static int multipath_run (mddev_t *mddev) * should be freed in multipath_stop()] */ - conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL); + conf = kmalloc(sizeof(multipath_conf_t), GFP_KERNEL); mddev->private = conf; if (!conf) { printk(KERN_ERR @@ -447,8 +452,9 @@ static int multipath_run (mddev_t *mddev) mdname(mddev)); goto out; } + memset(conf, 0, sizeof(*conf)); - conf->multipaths = kzalloc(sizeof(struct multipath_info)*mddev->raid_disks, + conf->multipaths = kmalloc(sizeof(struct multipath_info)*mddev->raid_disks, GFP_KERNEL); if (!conf->multipaths) { printk(KERN_ERR @@ -456,6 +462,7 @@ static int multipath_run (mddev_t *mddev) mdname(mddev)); goto out_free_conf; } + memset(conf->multipaths, 0, sizeof(struct multipath_info)*mddev->raid_disks); conf->working_disks = 0; ITERATE_RDEV(mddev,rdev,tmp) { @@ -550,10 +557,9 @@ static int multipath_stop (mddev_t *mddev) return 0; } -static struct mdk_personality multipath_personality = +static mdk_personality_t multipath_personality= { .name = "multipath", - .level = LEVEL_MULTIPATH, .owner = THIS_MODULE, .make_request = multipath_make_request, .run = multipath_run, @@ -566,17 +572,15 @@ static struct mdk_personality multipath_personality = static int __init multipath_init (void) { - return register_md_personality (&multipath_personality); + return register_md_personality (MULTIPATH, &multipath_personality); } static void __exit multipath_exit (void) { - unregister_md_personality (&multipath_personality); + unregister_md_personality (MULTIPATH); } module_init(multipath_init); module_exit(multipath_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS("md-personality-7"); /* MULTIPATH */ -MODULE_ALIAS("md-multipath"); -MODULE_ALIAS("md-level--4"); diff --git a/trunk/drivers/md/raid0.c b/trunk/drivers/md/raid0.c index abbca150202b..fece3277c2a5 100644 --- a/trunk/drivers/md/raid0.c +++ b/trunk/drivers/md/raid0.c @@ -113,16 +113,21 @@ static int create_strip_zones (mddev_t *mddev) } printk("raid0: FINAL %d zones\n", conf->nr_strip_zones); - conf->strip_zone = kzalloc(sizeof(struct strip_zone)* + conf->strip_zone = kmalloc(sizeof(struct strip_zone)* conf->nr_strip_zones, GFP_KERNEL); if (!conf->strip_zone) return 1; - conf->devlist = kzalloc(sizeof(mdk_rdev_t*)* + conf->devlist = kmalloc(sizeof(mdk_rdev_t*)* conf->nr_strip_zones*mddev->raid_disks, GFP_KERNEL); if (!conf->devlist) return 1; + memset(conf->strip_zone, 0,sizeof(struct strip_zone)* + conf->nr_strip_zones); + memset(conf->devlist, 0, + sizeof(mdk_rdev_t*) * conf->nr_strip_zones * mddev->raid_disks); + /* The first zone must contain all devices, so here we check that * there is a proper alignment of slots to devices and find them all */ @@ -275,11 +280,7 @@ static int raid0_run (mddev_t *mddev) mdk_rdev_t *rdev; struct list_head *tmp; - if (mddev->chunk_size == 0) { - printk(KERN_ERR "md/raid0: non-zero chunk size required.\n"); - return -EINVAL; - } - printk(KERN_INFO "%s: setting max_sectors to %d, segment boundary to %d\n", + printk("%s: setting max_sectors to %d, segment boundary to %d\n", mdname(mddev), mddev->chunk_size >> 9, (mddev->chunk_size>>1)-1); @@ -360,7 +361,7 @@ static int raid0_run (mddev_t *mddev) * chunksize should be used in that case. */ { - int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_SIZE; + int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE; if (mddev->queue->backing_dev_info.ra_pages < 2* stripe) mddev->queue->backing_dev_info.ra_pages = 2* stripe; } @@ -511,10 +512,9 @@ static void raid0_status (struct seq_file *seq, mddev_t *mddev) return; } -static struct mdk_personality raid0_personality= +static mdk_personality_t raid0_personality= { .name = "raid0", - .level = 0, .owner = THIS_MODULE, .make_request = raid0_make_request, .run = raid0_run, @@ -524,17 +524,15 @@ static struct mdk_personality raid0_personality= static int __init raid0_init (void) { - return register_md_personality (&raid0_personality); + return register_md_personality (RAID0, &raid0_personality); } static void raid0_exit (void) { - unregister_md_personality (&raid0_personality); + unregister_md_personality (RAID0); } module_init(raid0_init); module_exit(raid0_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS("md-personality-2"); /* RAID0 */ -MODULE_ALIAS("md-raid0"); -MODULE_ALIAS("md-level-0"); diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index a06ff91f27e2..229d7b204297 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -47,11 +47,10 @@ */ #define NR_RAID1_BIOS 256 +static mdk_personality_t raid1_personality; static void unplug_slaves(mddev_t *mddev); -static void allow_barrier(conf_t *conf); -static void lower_barrier(conf_t *conf); static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data) { @@ -60,8 +59,10 @@ static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data) int size = offsetof(r1bio_t, bios[pi->raid_disks]); /* allocate a r1bio with room for raid_disks entries in the bios array */ - r1_bio = kzalloc(size, gfp_flags); - if (!r1_bio) + r1_bio = kmalloc(size, gfp_flags); + if (r1_bio) + memset(r1_bio, 0, size); + else unplug_slaves(pi->mddev); return r1_bio; @@ -103,30 +104,15 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data) } /* * Allocate RESYNC_PAGES data pages and attach them to - * the first bio. - * If this is a user-requested check/repair, allocate - * RESYNC_PAGES for each bio. + * the first bio; */ - if (test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery)) - j = pi->raid_disks; - else - j = 1; - while(j--) { - bio = r1_bio->bios[j]; - for (i = 0; i < RESYNC_PAGES; i++) { - page = alloc_page(gfp_flags); - if (unlikely(!page)) - goto out_free_pages; - - bio->bi_io_vec[i].bv_page = page; - } - } - /* If not user-requests, copy the page pointers to all bios */ - if (!test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery)) { - for (i=0; iraid_disks; j++) - r1_bio->bios[j]->bi_io_vec[i].bv_page = - r1_bio->bios[0]->bi_io_vec[i].bv_page; + bio = r1_bio->bios[0]; + for (i = 0; i < RESYNC_PAGES; i++) { + page = alloc_page(gfp_flags); + if (unlikely(!page)) + goto out_free_pages; + + bio->bi_io_vec[i].bv_page = page; } r1_bio->master_bio = NULL; @@ -134,10 +120,8 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data) return r1_bio; out_free_pages: - for (i=0; i < RESYNC_PAGES ; i++) - for (j=0 ; j < pi->raid_disks; j++) - safe_put_page(r1_bio->bios[j]->bi_io_vec[i].bv_page); - j = -1; + for ( ; i > 0 ; i--) + __free_page(bio->bi_io_vec[i-1].bv_page); out_free_bio: while ( ++j < pi->raid_disks ) bio_put(r1_bio->bios[j]); @@ -148,16 +132,14 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data) static void r1buf_pool_free(void *__r1_bio, void *data) { struct pool_info *pi = data; - int i,j; + int i; r1bio_t *r1bio = __r1_bio; + struct bio *bio = r1bio->bios[0]; - for (i = 0; i < RESYNC_PAGES; i++) - for (j = pi->raid_disks; j-- ;) { - if (j == 0 || - r1bio->bios[j]->bi_io_vec[i].bv_page != - r1bio->bios[0]->bi_io_vec[i].bv_page) - safe_put_page(r1bio->bios[j]->bi_io_vec[i].bv_page); - } + for (i = 0; i < RESYNC_PAGES; i++) { + __free_page(bio->bi_io_vec[i].bv_page); + bio->bi_io_vec[i].bv_page = NULL; + } for (i=0 ; i < pi->raid_disks; i++) bio_put(r1bio->bios[i]); @@ -170,7 +152,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio) for (i = 0; i < conf->raid_disks; i++) { struct bio **bio = r1_bio->bios + i; - if (*bio && *bio != IO_BLOCKED) + if (*bio) bio_put(*bio); *bio = NULL; } @@ -178,13 +160,20 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio) static inline void free_r1bio(r1bio_t *r1_bio) { + unsigned long flags; + conf_t *conf = mddev_to_conf(r1_bio->mddev); /* * Wake up any possible resync thread that waits for the device * to go idle. */ - allow_barrier(conf); + spin_lock_irqsave(&conf->resync_lock, flags); + if (!--conf->nr_pending) { + wake_up(&conf->wait_idle); + wake_up(&conf->wait_resume); + } + spin_unlock_irqrestore(&conf->resync_lock, flags); put_all_bios(conf, r1_bio); mempool_free(r1_bio, conf->r1bio_pool); @@ -193,17 +182,22 @@ static inline void free_r1bio(r1bio_t *r1_bio) static inline void put_buf(r1bio_t *r1_bio) { conf_t *conf = mddev_to_conf(r1_bio->mddev); - int i; - - for (i=0; iraid_disks; i++) { - struct bio *bio = r1_bio->bios[i]; - if (bio->bi_end_io) - rdev_dec_pending(conf->mirrors[i].rdev, r1_bio->mddev); - } + unsigned long flags; mempool_free(r1_bio, conf->r1buf_pool); - lower_barrier(conf); + spin_lock_irqsave(&conf->resync_lock, flags); + if (!conf->barrier) + BUG(); + --conf->barrier; + wake_up(&conf->wait_resume); + wake_up(&conf->wait_idle); + + if (!--conf->nr_pending) { + wake_up(&conf->wait_idle); + wake_up(&conf->wait_resume); + } + spin_unlock_irqrestore(&conf->resync_lock, flags); } static void reschedule_retry(r1bio_t *r1_bio) @@ -214,10 +208,8 @@ static void reschedule_retry(r1bio_t *r1_bio) spin_lock_irqsave(&conf->device_lock, flags); list_add(&r1_bio->retry_list, &conf->retry_list); - conf->nr_queued ++; spin_unlock_irqrestore(&conf->device_lock, flags); - wake_up(&conf->wait_barrier); md_wakeup_thread(mddev->thread); } @@ -269,9 +261,9 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int /* * this branch is our 'one mirror IO has finished' event handler: */ - update_head_pos(mirror, r1_bio); - - if (uptodate || conf->working_disks <= 1) { + if (!uptodate) + md_error(r1_bio->mddev, conf->mirrors[mirror].rdev); + else /* * Set R1BIO_Uptodate in our master bio, so that * we will return a good error code for to the higher @@ -281,11 +273,16 @@ static int raid1_end_read_request(struct bio *bio, unsigned int bytes_done, int * user-side. So if something waits for IO, then it will * wait for the 'master' bio. */ - if (uptodate) - set_bit(R1BIO_Uptodate, &r1_bio->state); + set_bit(R1BIO_Uptodate, &r1_bio->state); + update_head_pos(mirror, r1_bio); + + /* + * we have only one bio on the read side + */ + if (uptodate) raid_end_bio_io(r1_bio); - } else { + else { /* * oops, read error: */ @@ -381,7 +378,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int /* free extra copy of the data pages */ int i = bio->bi_vcnt; while (i--) - safe_put_page(bio->bi_io_vec[i].bv_page); + __free_page(bio->bi_io_vec[i].bv_page); } /* clear the bitmap if all writes complete successfully */ bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector, @@ -436,13 +433,11 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) new_disk = 0; for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); - r1_bio->bios[new_disk] == IO_BLOCKED || !rdev || !test_bit(In_sync, &rdev->flags) || test_bit(WriteMostly, &rdev->flags); rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) { - if (rdev && test_bit(In_sync, &rdev->flags) && - r1_bio->bios[new_disk] != IO_BLOCKED) + if (rdev && test_bit(In_sync, &rdev->flags)) wonly_disk = new_disk; if (new_disk == conf->raid_disks - 1) { @@ -456,13 +451,11 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) /* make sure the disk is operational */ for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); - r1_bio->bios[new_disk] == IO_BLOCKED || !rdev || !test_bit(In_sync, &rdev->flags) || test_bit(WriteMostly, &rdev->flags); rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) { - if (rdev && test_bit(In_sync, &rdev->flags) && - r1_bio->bios[new_disk] != IO_BLOCKED) + if (rdev && test_bit(In_sync, &rdev->flags)) wonly_disk = new_disk; if (new_disk <= 0) @@ -499,7 +492,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) rdev = rcu_dereference(conf->mirrors[disk].rdev); - if (!rdev || r1_bio->bios[disk] == IO_BLOCKED || + if (!rdev || !test_bit(In_sync, &rdev->flags) || test_bit(WriteMostly, &rdev->flags)) continue; @@ -527,7 +520,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) /* cannot risk returning a device that failed * before we inc'ed nr_pending */ - rdev_dec_pending(rdev, conf->mddev); + atomic_dec(&rdev->nr_pending); goto retry; } conf->next_seq_sect = this_sector + sectors; @@ -600,119 +593,42 @@ static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk, return ret; } -/* Barriers.... - * Sometimes we need to suspend IO while we do something else, - * either some resync/recovery, or reconfigure the array. - * To do this we raise a 'barrier'. - * The 'barrier' is a counter that can be raised multiple times - * to count how many activities are happening which preclude - * normal IO. - * We can only raise the barrier if there is no pending IO. - * i.e. if nr_pending == 0. - * We choose only to raise the barrier if no-one is waiting for the - * barrier to go down. This means that as soon as an IO request - * is ready, no other operations which require a barrier will start - * until the IO request has had a chance. - * - * So: regular IO calls 'wait_barrier'. When that returns there - * is no backgroup IO happening, It must arrange to call - * allow_barrier when it has finished its IO. - * backgroup IO calls must call raise_barrier. Once that returns - * there is no normal IO happeing. It must arrange to call - * lower_barrier when the particular background IO completes. +/* + * Throttle resync depth, so that we can both get proper overlapping of + * requests, but are still able to handle normal requests quickly. */ #define RESYNC_DEPTH 32 -static void raise_barrier(conf_t *conf) -{ - spin_lock_irq(&conf->resync_lock); - - /* Wait until no block IO is waiting */ - wait_event_lock_irq(conf->wait_barrier, !conf->nr_waiting, - conf->resync_lock, - raid1_unplug(conf->mddev->queue)); - - /* block any new IO from starting */ - conf->barrier++; - - /* No wait for all pending IO to complete */ - wait_event_lock_irq(conf->wait_barrier, - !conf->nr_pending && conf->barrier < RESYNC_DEPTH, - conf->resync_lock, - raid1_unplug(conf->mddev->queue)); - - spin_unlock_irq(&conf->resync_lock); -} - -static void lower_barrier(conf_t *conf) -{ - unsigned long flags; - spin_lock_irqsave(&conf->resync_lock, flags); - conf->barrier--; - spin_unlock_irqrestore(&conf->resync_lock, flags); - wake_up(&conf->wait_barrier); -} - -static void wait_barrier(conf_t *conf) +static void device_barrier(conf_t *conf, sector_t sect) { spin_lock_irq(&conf->resync_lock); - if (conf->barrier) { - conf->nr_waiting++; - wait_event_lock_irq(conf->wait_barrier, !conf->barrier, - conf->resync_lock, - raid1_unplug(conf->mddev->queue)); - conf->nr_waiting--; + wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume), + conf->resync_lock, raid1_unplug(conf->mddev->queue)); + + if (!conf->barrier++) { + wait_event_lock_irq(conf->wait_idle, !conf->nr_pending, + conf->resync_lock, raid1_unplug(conf->mddev->queue)); + if (conf->nr_pending) + BUG(); } - conf->nr_pending++; - spin_unlock_irq(&conf->resync_lock); -} - -static void allow_barrier(conf_t *conf) -{ - unsigned long flags; - spin_lock_irqsave(&conf->resync_lock, flags); - conf->nr_pending--; - spin_unlock_irqrestore(&conf->resync_lock, flags); - wake_up(&conf->wait_barrier); -} - -static void freeze_array(conf_t *conf) -{ - /* stop syncio and normal IO and wait for everything to - * go quite. - * We increment barrier and nr_waiting, and then - * wait until barrier+nr_pending match nr_queued+2 - */ - spin_lock_irq(&conf->resync_lock); - conf->barrier++; - conf->nr_waiting++; - wait_event_lock_irq(conf->wait_barrier, - conf->barrier+conf->nr_pending == conf->nr_queued+2, - conf->resync_lock, - raid1_unplug(conf->mddev->queue)); - spin_unlock_irq(&conf->resync_lock); -} -static void unfreeze_array(conf_t *conf) -{ - /* reverse the effect of the freeze */ - spin_lock_irq(&conf->resync_lock); - conf->barrier--; - conf->nr_waiting--; - wake_up(&conf->wait_barrier); + wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH, + conf->resync_lock, raid1_unplug(conf->mddev->queue)); + conf->next_resync = sect; spin_unlock_irq(&conf->resync_lock); } - /* duplicate the data pages for behind I/O */ static struct page **alloc_behind_pages(struct bio *bio) { int i; struct bio_vec *bvec; - struct page **pages = kzalloc(bio->bi_vcnt * sizeof(struct page *), + struct page **pages = kmalloc(bio->bi_vcnt * sizeof(struct page *), GFP_NOIO); if (unlikely(!pages)) goto do_sync_io; + memset(pages, 0, bio->bi_vcnt * sizeof(struct page *)); + bio_for_each_segment(bvec, bio, i) { pages[i] = alloc_page(GFP_NOIO); if (unlikely(!pages[i])) @@ -728,7 +644,7 @@ static struct page **alloc_behind_pages(struct bio *bio) do_sync_io: if (pages) for (i = 0; i < bio->bi_vcnt && pages[i]; i++) - put_page(pages[i]); + __free_page(pages[i]); kfree(pages); PRINTK("%dB behind alloc failed, doing sync I/O\n", bio->bi_size); return NULL; @@ -762,7 +678,10 @@ static int make_request(request_queue_t *q, struct bio * bio) */ md_write_start(mddev, bio); /* wait on superblock update early */ - wait_barrier(conf); + spin_lock_irq(&conf->resync_lock); + wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, ); + conf->nr_pending++; + spin_unlock_irq(&conf->resync_lock); disk_stat_inc(mddev->gendisk, ios[rw]); disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); @@ -830,7 +749,7 @@ static int make_request(request_queue_t *q, struct bio * bio) !test_bit(Faulty, &rdev->flags)) { atomic_inc(&rdev->nr_pending); if (test_bit(Faulty, &rdev->flags)) { - rdev_dec_pending(rdev, mddev); + atomic_dec(&rdev->nr_pending); r1_bio->bios[i] = NULL; } else r1_bio->bios[i] = bio; @@ -990,8 +909,13 @@ static void print_conf(conf_t *conf) static void close_sync(conf_t *conf) { - wait_barrier(conf); - allow_barrier(conf); + spin_lock_irq(&conf->resync_lock); + wait_event_lock_irq(conf->wait_resume, !conf->barrier, + conf->resync_lock, raid1_unplug(conf->mddev->queue)); + spin_unlock_irq(&conf->resync_lock); + + if (conf->barrier) BUG(); + if (waitqueue_active(&conf->wait_idle)) BUG(); mempool_destroy(conf->r1buf_pool); conf->r1buf_pool = NULL; @@ -1091,27 +1015,28 @@ static int raid1_remove_disk(mddev_t *mddev, int number) static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) { + int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); - int i; + conf_t *conf = mddev_to_conf(r1_bio->mddev); if (bio->bi_size) return 1; - for (i=r1_bio->mddev->raid_disks; i--; ) - if (r1_bio->bios[i] == bio) - break; - BUG_ON(i < 0); - update_head_pos(i, r1_bio); + if (r1_bio->bios[r1_bio->read_disk] != bio) + BUG(); + update_head_pos(r1_bio->read_disk, r1_bio); /* * we have read a block, now it needs to be re-written, * or re-read if the read failed. * We don't do much here, just schedule handling by raid1d */ - if (test_bit(BIO_UPTODATE, &bio->bi_flags)) + if (!uptodate) { + md_error(r1_bio->mddev, + conf->mirrors[r1_bio->read_disk].rdev); + } else set_bit(R1BIO_Uptodate, &r1_bio->state); - - if (atomic_dec_and_test(&r1_bio->remaining)) - reschedule_retry(r1_bio); + rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev); + reschedule_retry(r1_bio); return 0; } @@ -1141,6 +1066,7 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) md_done_sync(mddev, r1_bio->sectors, uptodate); put_buf(r1_bio); } + rdev_dec_pending(conf->mirrors[mirror].rdev, mddev); return 0; } @@ -1153,173 +1079,34 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) bio = r1_bio->bios[r1_bio->read_disk]; - - if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { - /* We have read all readable devices. If we haven't - * got the block, then there is no hope left. - * If we have, then we want to do a comparison - * and skip the write if everything is the same. - * If any blocks failed to read, then we need to - * attempt an over-write - */ - int primary; - if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) { - for (i=0; iraid_disks; i++) - if (r1_bio->bios[i]->bi_end_io == end_sync_read) - md_error(mddev, conf->mirrors[i].rdev); - - md_done_sync(mddev, r1_bio->sectors, 1); - put_buf(r1_bio); - return; - } - for (primary=0; primaryraid_disks; primary++) - if (r1_bio->bios[primary]->bi_end_io == end_sync_read && - test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) { - r1_bio->bios[primary]->bi_end_io = NULL; - rdev_dec_pending(conf->mirrors[primary].rdev, mddev); - break; - } - r1_bio->read_disk = primary; - for (i=0; iraid_disks; i++) - if (r1_bio->bios[i]->bi_end_io == end_sync_read && - test_bit(BIO_UPTODATE, &r1_bio->bios[i]->bi_flags)) { - int j; - int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9); - struct bio *pbio = r1_bio->bios[primary]; - struct bio *sbio = r1_bio->bios[i]; - for (j = vcnt; j-- ; ) - if (memcmp(page_address(pbio->bi_io_vec[j].bv_page), - page_address(sbio->bi_io_vec[j].bv_page), - PAGE_SIZE)) - break; - if (j >= 0) - mddev->resync_mismatches += r1_bio->sectors; - if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) { - sbio->bi_end_io = NULL; - rdev_dec_pending(conf->mirrors[i].rdev, mddev); - } else { - /* fixup the bio for reuse */ - sbio->bi_vcnt = vcnt; - sbio->bi_size = r1_bio->sectors << 9; - sbio->bi_idx = 0; - sbio->bi_phys_segments = 0; - sbio->bi_hw_segments = 0; - sbio->bi_hw_front_size = 0; - sbio->bi_hw_back_size = 0; - sbio->bi_flags &= ~(BIO_POOL_MASK - 1); - sbio->bi_flags |= 1 << BIO_UPTODATE; - sbio->bi_next = NULL; - sbio->bi_sector = r1_bio->sector + - conf->mirrors[i].rdev->data_offset; - sbio->bi_bdev = conf->mirrors[i].rdev->bdev; - } - } - } +/* + if (r1_bio->sector == 0) printk("First sync write startss\n"); +*/ + /* + * schedule writes + */ if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) { - /* ouch - failed to read all of that. - * Try some synchronous reads of other devices to get - * good data, much like with normal read errors. Only - * read into the pages we already have so they we don't - * need to re-issue the read request. - * We don't need to freeze the array, because being in an - * active sync request, there is no normal IO, and - * no overlapping syncs. + /* + * There is no point trying a read-for-reconstruct as + * reconstruct is about to be aborted */ - sector_t sect = r1_bio->sector; - int sectors = r1_bio->sectors; - int idx = 0; - - while(sectors) { - int s = sectors; - int d = r1_bio->read_disk; - int success = 0; - mdk_rdev_t *rdev; - - if (s > (PAGE_SIZE>>9)) - s = PAGE_SIZE >> 9; - do { - if (r1_bio->bios[d]->bi_end_io == end_sync_read) { - rdev = conf->mirrors[d].rdev; - if (sync_page_io(rdev->bdev, - sect + rdev->data_offset, - s<<9, - bio->bi_io_vec[idx].bv_page, - READ)) { - success = 1; - break; - } - } - d++; - if (d == conf->raid_disks) - d = 0; - } while (!success && d != r1_bio->read_disk); - - if (success) { - int start = d; - /* write it back and re-read */ - set_bit(R1BIO_Uptodate, &r1_bio->state); - while (d != r1_bio->read_disk) { - if (d == 0) - d = conf->raid_disks; - d--; - if (r1_bio->bios[d]->bi_end_io != end_sync_read) - continue; - rdev = conf->mirrors[d].rdev; - atomic_add(s, &rdev->corrected_errors); - if (sync_page_io(rdev->bdev, - sect + rdev->data_offset, - s<<9, - bio->bi_io_vec[idx].bv_page, - WRITE) == 0) - md_error(mddev, rdev); - } - d = start; - while (d != r1_bio->read_disk) { - if (d == 0) - d = conf->raid_disks; - d--; - if (r1_bio->bios[d]->bi_end_io != end_sync_read) - continue; - rdev = conf->mirrors[d].rdev; - if (sync_page_io(rdev->bdev, - sect + rdev->data_offset, - s<<9, - bio->bi_io_vec[idx].bv_page, - READ) == 0) - md_error(mddev, rdev); - } - } else { - char b[BDEVNAME_SIZE]; - /* Cannot read from anywhere, array is toast */ - md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev); - printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error" - " for block %llu\n", - bdevname(bio->bi_bdev,b), - (unsigned long long)r1_bio->sector); - md_done_sync(mddev, r1_bio->sectors, 0); - put_buf(r1_bio); - return; - } - sectors -= s; - sect += s; - idx ++; - } + char b[BDEVNAME_SIZE]; + printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error" + " for block %llu\n", + bdevname(bio->bi_bdev,b), + (unsigned long long)r1_bio->sector); + md_done_sync(mddev, r1_bio->sectors, 0); + put_buf(r1_bio); + return; } - /* - * schedule writes - */ atomic_set(&r1_bio->remaining, 1); for (i = 0; i < disks ; i++) { wbio = r1_bio->bios[i]; - if (wbio->bi_end_io == NULL || - (wbio->bi_end_io == end_sync_read && - (i == r1_bio->read_disk || - !test_bit(MD_RECOVERY_SYNC, &mddev->recovery)))) + if (wbio->bi_end_io != end_sync_write) continue; - wbio->bi_rw = WRITE; - wbio->bi_end_io = end_sync_write; + atomic_inc(&conf->mirrors[i].rdev->nr_pending); atomic_inc(&r1_bio->remaining); md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9); @@ -1380,7 +1167,6 @@ static void raid1d(mddev_t *mddev) break; r1_bio = list_entry(head->prev, r1bio_t, retry_list); list_del(head->prev); - conf->nr_queued--; spin_unlock_irqrestore(&conf->device_lock, flags); mddev = r1_bio->mddev; @@ -1420,86 +1206,6 @@ static void raid1d(mddev_t *mddev) } } else { int disk; - - /* we got a read error. Maybe the drive is bad. Maybe just - * the block and we can fix it. - * We freeze all other IO, and try reading the block from - * other devices. When we find one, we re-write - * and check it that fixes the read error. - * This is all done synchronously while the array is - * frozen - */ - sector_t sect = r1_bio->sector; - int sectors = r1_bio->sectors; - freeze_array(conf); - if (mddev->ro == 0) while(sectors) { - int s = sectors; - int d = r1_bio->read_disk; - int success = 0; - - if (s > (PAGE_SIZE>>9)) - s = PAGE_SIZE >> 9; - - do { - rdev = conf->mirrors[d].rdev; - if (rdev && - test_bit(In_sync, &rdev->flags) && - sync_page_io(rdev->bdev, - sect + rdev->data_offset, - s<<9, - conf->tmppage, READ)) - success = 1; - else { - d++; - if (d == conf->raid_disks) - d = 0; - } - } while (!success && d != r1_bio->read_disk); - - if (success) { - /* write it back and re-read */ - int start = d; - while (d != r1_bio->read_disk) { - if (d==0) - d = conf->raid_disks; - d--; - rdev = conf->mirrors[d].rdev; - atomic_add(s, &rdev->corrected_errors); - if (rdev && - test_bit(In_sync, &rdev->flags)) { - if (sync_page_io(rdev->bdev, - sect + rdev->data_offset, - s<<9, conf->tmppage, WRITE) == 0) - /* Well, this device is dead */ - md_error(mddev, rdev); - } - } - d = start; - while (d != r1_bio->read_disk) { - if (d==0) - d = conf->raid_disks; - d--; - rdev = conf->mirrors[d].rdev; - if (rdev && - test_bit(In_sync, &rdev->flags)) { - if (sync_page_io(rdev->bdev, - sect + rdev->data_offset, - s<<9, conf->tmppage, READ) == 0) - /* Well, this device is dead */ - md_error(mddev, rdev); - } - } - } else { - /* Cannot read from anywhere -- bye bye array */ - md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev); - break; - } - sectors -= s; - sect += s; - } - - unfreeze_array(conf); - bio = r1_bio->bios[r1_bio->read_disk]; if ((disk=read_balance(conf, r1_bio)) == -1) { printk(KERN_ALERT "raid1: %s: unrecoverable I/O" @@ -1508,8 +1214,7 @@ static void raid1d(mddev_t *mddev) (unsigned long long)r1_bio->sector); raid_end_bio_io(r1_bio); } else { - r1_bio->bios[r1_bio->read_disk] = - mddev->ro ? IO_BLOCKED : NULL; + r1_bio->bios[r1_bio->read_disk] = NULL; r1_bio->read_disk = disk; bio_put(bio); bio = bio_clone(r1_bio->master_bio, GFP_NOIO); @@ -1564,13 +1269,14 @@ static int init_resync(conf_t *conf) static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster) { conf_t *conf = mddev_to_conf(mddev); + mirror_info_t *mirror; r1bio_t *r1_bio; struct bio *bio; sector_t max_sector, nr_sectors; - int disk = -1; + int disk; int i; - int wonly = -1; - int write_targets = 0, read_targets = 0; + int wonly; + int write_targets = 0; int sync_blocks; int still_degraded = 0; @@ -1611,35 +1317,55 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i return sync_blocks; } /* - * If there is non-resync activity waiting for a turn, - * and resync is going fast enough, - * then let it though before starting on this new sync request. + * If there is non-resync activity waiting for us then + * put in a delay to throttle resync. */ - if (!go_faster && conf->nr_waiting) + if (!go_faster && waitqueue_active(&conf->wait_resume)) msleep_interruptible(1000); + device_barrier(conf, sector_nr + RESYNC_SECTORS); + + /* + * If reconstructing, and >1 working disc, + * could dedicate one to rebuild and others to + * service read requests .. + */ + disk = conf->last_used; + /* make sure disk is operational */ + wonly = disk; + while (conf->mirrors[disk].rdev == NULL || + !test_bit(In_sync, &conf->mirrors[disk].rdev->flags) || + test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags) + ) { + if (conf->mirrors[disk].rdev && + test_bit(In_sync, &conf->mirrors[disk].rdev->flags)) + wonly = disk; + if (disk <= 0) + disk = conf->raid_disks; + disk--; + if (disk == conf->last_used) { + disk = wonly; + break; + } + } + conf->last_used = disk; + atomic_inc(&conf->mirrors[disk].rdev->nr_pending); - raise_barrier(conf); - conf->next_resync = sector_nr; + mirror = conf->mirrors + disk; r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO); - rcu_read_lock(); - /* - * If we get a correctably read error during resync or recovery, - * we might want to read from a different device. So we - * flag all drives that could conceivably be read from for READ, - * and any others (which will be non-In_sync devices) for WRITE. - * If a read fails, we try reading from something else for which READ - * is OK. - */ + + spin_lock_irq(&conf->resync_lock); + conf->nr_pending++; + spin_unlock_irq(&conf->resync_lock); r1_bio->mddev = mddev; r1_bio->sector = sector_nr; r1_bio->state = 0; set_bit(R1BIO_IsSync, &r1_bio->state); + r1_bio->read_disk = disk; for (i=0; i < conf->raid_disks; i++) { - mdk_rdev_t *rdev; bio = r1_bio->bios[i]; /* take from bio_init */ @@ -1654,49 +1380,35 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i bio->bi_end_io = NULL; bio->bi_private = NULL; - rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev == NULL || - test_bit(Faulty, &rdev->flags)) { + if (i == disk) { + bio->bi_rw = READ; + bio->bi_end_io = end_sync_read; + } else if (conf->mirrors[i].rdev == NULL || + test_bit(Faulty, &conf->mirrors[i].rdev->flags)) { still_degraded = 1; continue; - } else if (!test_bit(In_sync, &rdev->flags)) { + } else if (!test_bit(In_sync, &conf->mirrors[i].rdev->flags) || + sector_nr + RESYNC_SECTORS > mddev->recovery_cp || + test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { bio->bi_rw = WRITE; bio->bi_end_io = end_sync_write; write_targets ++; - } else { - /* may need to read from here */ - bio->bi_rw = READ; - bio->bi_end_io = end_sync_read; - if (test_bit(WriteMostly, &rdev->flags)) { - if (wonly < 0) - wonly = i; - } else { - if (disk < 0) - disk = i; - } - read_targets++; - } - atomic_inc(&rdev->nr_pending); - bio->bi_sector = sector_nr + rdev->data_offset; - bio->bi_bdev = rdev->bdev; + } else + /* no need to read or write here */ + continue; + bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset; + bio->bi_bdev = conf->mirrors[i].rdev->bdev; bio->bi_private = r1_bio; } - rcu_read_unlock(); - if (disk < 0) - disk = wonly; - r1_bio->read_disk = disk; - - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && read_targets > 0) - /* extra read targets are also write targets */ - write_targets += read_targets-1; - if (write_targets == 0 || read_targets == 0) { + if (write_targets == 0) { /* There is nowhere to write, so all non-sync * drives must be failed - so we are finished */ sector_t rv = max_sector - sector_nr; *skipped = 1; put_buf(r1_bio); + rdev_dec_pending(conf->mirrors[disk].rdev, mddev); return rv; } @@ -1724,10 +1436,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (i=0 ; i < conf->raid_disks; i++) { bio = r1_bio->bios[i]; if (bio->bi_end_io) { - page = bio->bi_io_vec[bio->bi_vcnt].bv_page; + page = r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page; if (bio_add_page(bio, page, len, 0) == 0) { /* stop here */ - bio->bi_io_vec[bio->bi_vcnt].bv_page = page; + r1_bio->bios[0]->bi_io_vec[bio->bi_vcnt].bv_page = page; while (i > 0) { i--; bio = r1_bio->bios[i]; @@ -1747,28 +1459,12 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i sync_blocks -= (len>>9); } while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES); bio_full: + bio = r1_bio->bios[disk]; r1_bio->sectors = nr_sectors; - /* For a user-requested sync, we read all readable devices and do a - * compare - */ - if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { - atomic_set(&r1_bio->remaining, read_targets); - for (i=0; iraid_disks; i++) { - bio = r1_bio->bios[i]; - if (bio->bi_end_io == end_sync_read) { - md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors); - generic_make_request(bio); - } - } - } else { - atomic_set(&r1_bio->remaining, 1); - bio = r1_bio->bios[r1_bio->read_disk]; - md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev, - nr_sectors); - generic_make_request(bio); + md_sync_acct(mirror->rdev->bdev, nr_sectors); - } + generic_make_request(bio); return nr_sectors; } @@ -1791,19 +1487,18 @@ static int run(mddev_t *mddev) * bookkeeping area. [whatever we allocate in run(), * should be freed in stop()] */ - conf = kzalloc(sizeof(conf_t), GFP_KERNEL); + conf = kmalloc(sizeof(conf_t), GFP_KERNEL); mddev->private = conf; if (!conf) goto out_no_mem; - conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks, + memset(conf, 0, sizeof(*conf)); + conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks, GFP_KERNEL); if (!conf->mirrors) goto out_no_mem; - conf->tmppage = alloc_page(GFP_KERNEL); - if (!conf->tmppage) - goto out_no_mem; + memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks); conf->poolinfo = kmalloc(sizeof(*conf->poolinfo), GFP_KERNEL); if (!conf->poolinfo) @@ -1847,7 +1542,8 @@ static int run(mddev_t *mddev) mddev->recovery_cp = MaxSector; spin_lock_init(&conf->resync_lock); - init_waitqueue_head(&conf->wait_barrier); + init_waitqueue_head(&conf->wait_idle); + init_waitqueue_head(&conf->wait_resume); bio_list_init(&conf->pending_bio_list); bio_list_init(&conf->flushing_bio_list); @@ -1887,6 +1583,7 @@ static int run(mddev_t *mddev) mdname(mddev)); goto out_free_conf; } + if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; printk(KERN_INFO "raid1: raid set %s active with %d out of %d mirrors\n", @@ -1911,7 +1608,6 @@ static int run(mddev_t *mddev) if (conf->r1bio_pool) mempool_destroy(conf->r1bio_pool); kfree(conf->mirrors); - safe_put_page(conf->tmppage); kfree(conf->poolinfo); kfree(conf); mddev->private = NULL; @@ -2010,14 +1706,19 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) kfree(newpoolinfo); return -ENOMEM; } - newmirrors = kzalloc(sizeof(struct mirror_info) * raid_disks, GFP_KERNEL); + newmirrors = kmalloc(sizeof(struct mirror_info) * raid_disks, GFP_KERNEL); if (!newmirrors) { kfree(newpoolinfo); mempool_destroy(newpool); return -ENOMEM; } + memset(newmirrors, 0, sizeof(struct mirror_info)*raid_disks); - raise_barrier(conf); + spin_lock_irq(&conf->resync_lock); + conf->barrier++; + wait_event_lock_irq(conf->wait_idle, !conf->nr_pending, + conf->resync_lock, raid1_unplug(mddev->queue)); + spin_unlock_irq(&conf->resync_lock); /* ok, everything is stopped */ oldpool = conf->r1bio_pool; @@ -2037,7 +1738,12 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks) conf->raid_disks = mddev->raid_disks = raid_disks; conf->last_used = 0; /* just make sure it is in-range */ - lower_barrier(conf); + spin_lock_irq(&conf->resync_lock); + conf->barrier--; + spin_unlock_irq(&conf->resync_lock); + wake_up(&conf->wait_resume); + wake_up(&conf->wait_idle); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); @@ -2052,19 +1758,33 @@ static void raid1_quiesce(mddev_t *mddev, int state) switch(state) { case 1: - raise_barrier(conf); + spin_lock_irq(&conf->resync_lock); + conf->barrier++; + wait_event_lock_irq(conf->wait_idle, !conf->nr_pending, + conf->resync_lock, raid1_unplug(mddev->queue)); + spin_unlock_irq(&conf->resync_lock); break; case 0: - lower_barrier(conf); + spin_lock_irq(&conf->resync_lock); + conf->barrier--; + spin_unlock_irq(&conf->resync_lock); + wake_up(&conf->wait_resume); + wake_up(&conf->wait_idle); break; } + if (mddev->thread) { + if (mddev->bitmap) + mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; + else + mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; + md_wakeup_thread(mddev->thread); + } } -static struct mdk_personality raid1_personality = +static mdk_personality_t raid1_personality = { .name = "raid1", - .level = 1, .owner = THIS_MODULE, .make_request = make_request, .run = run, @@ -2082,17 +1802,15 @@ static struct mdk_personality raid1_personality = static int __init raid_init(void) { - return register_md_personality(&raid1_personality); + return register_md_personality(RAID1, &raid1_personality); } static void raid_exit(void) { - unregister_md_personality(&raid1_personality); + unregister_md_personality(RAID1); } module_init(raid_init); module_exit(raid_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS("md-personality-3"); /* RAID1 */ -MODULE_ALIAS("md-raid1"); -MODULE_ALIAS("md-level-1"); diff --git a/trunk/drivers/md/raid10.c b/trunk/drivers/md/raid10.c index 9e658e519a27..713dc9c2c730 100644 --- a/trunk/drivers/md/raid10.c +++ b/trunk/drivers/md/raid10.c @@ -18,9 +18,7 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "dm-bio-list.h" #include -#include /* * RAID10 provides a combination of RAID0 and RAID1 functionality. @@ -49,9 +47,6 @@ static void unplug_slaves(mddev_t *mddev); -static void allow_barrier(conf_t *conf); -static void lower_barrier(conf_t *conf); - static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data) { conf_t *conf = data; @@ -59,8 +54,10 @@ static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data) int size = offsetof(struct r10bio_s, devs[conf->copies]); /* allocate a r10bio with room for raid_disks entries in the bios array */ - r10_bio = kzalloc(size, gfp_flags); - if (!r10_bio) + r10_bio = kmalloc(size, gfp_flags); + if (r10_bio) + memset(r10_bio, 0, size); + else unplug_slaves(conf->mddev); return r10_bio; @@ -132,10 +129,10 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data) out_free_pages: for ( ; i > 0 ; i--) - safe_put_page(bio->bi_io_vec[i-1].bv_page); + __free_page(bio->bi_io_vec[i-1].bv_page); while (j--) for (i = 0; i < RESYNC_PAGES ; i++) - safe_put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page); + __free_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page); j = -1; out_free_bio: while ( ++j < nalloc ) @@ -155,7 +152,7 @@ static void r10buf_pool_free(void *__r10_bio, void *data) struct bio *bio = r10bio->devs[j].bio; if (bio) { for (i = 0; i < RESYNC_PAGES; i++) { - safe_put_page(bio->bi_io_vec[i].bv_page); + __free_page(bio->bi_io_vec[i].bv_page); bio->bi_io_vec[i].bv_page = NULL; } bio_put(bio); @@ -170,7 +167,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio) for (i = 0; i < conf->copies; i++) { struct bio **bio = & r10_bio->devs[i].bio; - if (*bio && *bio != IO_BLOCKED) + if (*bio) bio_put(*bio); *bio = NULL; } @@ -178,13 +175,20 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio) static inline void free_r10bio(r10bio_t *r10_bio) { + unsigned long flags; + conf_t *conf = mddev_to_conf(r10_bio->mddev); /* * Wake up any possible resync thread that waits for the device * to go idle. */ - allow_barrier(conf); + spin_lock_irqsave(&conf->resync_lock, flags); + if (!--conf->nr_pending) { + wake_up(&conf->wait_idle); + wake_up(&conf->wait_resume); + } + spin_unlock_irqrestore(&conf->resync_lock, flags); put_all_bios(conf, r10_bio); mempool_free(r10_bio, conf->r10bio_pool); @@ -193,10 +197,22 @@ static inline void free_r10bio(r10bio_t *r10_bio) static inline void put_buf(r10bio_t *r10_bio) { conf_t *conf = mddev_to_conf(r10_bio->mddev); + unsigned long flags; mempool_free(r10_bio, conf->r10buf_pool); - lower_barrier(conf); + spin_lock_irqsave(&conf->resync_lock, flags); + if (!conf->barrier) + BUG(); + --conf->barrier; + wake_up(&conf->wait_resume); + wake_up(&conf->wait_idle); + + if (!--conf->nr_pending) { + wake_up(&conf->wait_idle); + wake_up(&conf->wait_resume); + } + spin_unlock_irqrestore(&conf->resync_lock, flags); } static void reschedule_retry(r10bio_t *r10_bio) @@ -207,7 +223,6 @@ static void reschedule_retry(r10bio_t *r10_bio) spin_lock_irqsave(&conf->device_lock, flags); list_add(&r10_bio->retry_list, &conf->retry_list); - conf->nr_queued ++; spin_unlock_irqrestore(&conf->device_lock, flags); md_wakeup_thread(mddev->thread); @@ -253,9 +268,9 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int /* * this branch is our 'one mirror IO has finished' event handler: */ - update_head_pos(slot, r10_bio); - - if (uptodate) { + if (!uptodate) + md_error(r10_bio->mddev, conf->mirrors[dev].rdev); + else /* * Set R10BIO_Uptodate in our master bio, so that * we will return a good error code to the higher @@ -266,8 +281,15 @@ static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int * wait for the 'master' bio. */ set_bit(R10BIO_Uptodate, &r10_bio->state); + + update_head_pos(slot, r10_bio); + + /* + * we have only one bio on the read side + */ + if (uptodate) raid_end_bio_io(r10_bio); - } else { + else { /* * oops, read error: */ @@ -300,11 +322,9 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in /* * this branch is our 'one mirror IO has finished' event handler: */ - if (!uptodate) { + if (!uptodate) md_error(r10_bio->mddev, conf->mirrors[dev].rdev); - /* an I/O failed, we can't clear the bitmap */ - set_bit(R10BIO_Degraded, &r10_bio->state); - } else + else /* * Set R10BIO_Uptodate in our master bio, so that * we will return a good error code for to the higher @@ -324,11 +344,6 @@ static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, in * already. */ if (atomic_dec_and_test(&r10_bio->remaining)) { - /* clear the bitmap if all writes complete successfully */ - bitmap_endwrite(r10_bio->mddev->bitmap, r10_bio->sector, - r10_bio->sectors, - !test_bit(R10BIO_Degraded, &r10_bio->state), - 0); md_write_end(r10_bio->mddev); raid_end_bio_io(r10_bio); } @@ -487,9 +502,8 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) rcu_read_lock(); /* * Check if we can balance. We can balance on the whole - * device if no resync is going on (recovery is ok), or below - * the resync window. We take the first readable disk when - * above the resync window. + * device if no resync is going on, or below the resync window. + * We take the first readable disk when above the resync window. */ if (conf->mddev->recovery_cp < MaxSector && (this_sector + sectors >= conf->next_resync)) { @@ -498,7 +512,6 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) disk = r10_bio->devs[slot].devnum; while ((rdev = rcu_dereference(conf->mirrors[disk].rdev)) == NULL || - r10_bio->devs[slot].bio == IO_BLOCKED || !test_bit(In_sync, &rdev->flags)) { slot++; if (slot == conf->copies) { @@ -516,7 +529,6 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) slot = 0; disk = r10_bio->devs[slot].devnum; while ((rdev=rcu_dereference(conf->mirrors[disk].rdev)) == NULL || - r10_bio->devs[slot].bio == IO_BLOCKED || !test_bit(In_sync, &rdev->flags)) { slot ++; if (slot == conf->copies) { @@ -537,7 +549,6 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) if ((rdev=rcu_dereference(conf->mirrors[ndisk].rdev)) == NULL || - r10_bio->devs[nslot].bio == IO_BLOCKED || !test_bit(In_sync, &rdev->flags)) continue; @@ -596,10 +607,7 @@ static void unplug_slaves(mddev_t *mddev) static void raid10_unplug(request_queue_t *q) { - mddev_t *mddev = q->queuedata; - unplug_slaves(q->queuedata); - md_wakeup_thread(mddev->thread); } static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk, @@ -632,107 +640,27 @@ static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk, return ret; } -/* Barriers.... - * Sometimes we need to suspend IO while we do something else, - * either some resync/recovery, or reconfigure the array. - * To do this we raise a 'barrier'. - * The 'barrier' is a counter that can be raised multiple times - * to count how many activities are happening which preclude - * normal IO. - * We can only raise the barrier if there is no pending IO. - * i.e. if nr_pending == 0. - * We choose only to raise the barrier if no-one is waiting for the - * barrier to go down. This means that as soon as an IO request - * is ready, no other operations which require a barrier will start - * until the IO request has had a chance. - * - * So: regular IO calls 'wait_barrier'. When that returns there - * is no backgroup IO happening, It must arrange to call - * allow_barrier when it has finished its IO. - * backgroup IO calls must call raise_barrier. Once that returns - * there is no normal IO happeing. It must arrange to call - * lower_barrier when the particular background IO completes. +/* + * Throttle resync depth, so that we can both get proper overlapping of + * requests, but are still able to handle normal requests quickly. */ #define RESYNC_DEPTH 32 -static void raise_barrier(conf_t *conf, int force) -{ - BUG_ON(force && !conf->barrier); - spin_lock_irq(&conf->resync_lock); - - /* Wait until no block IO is waiting (unless 'force') */ - wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting, - conf->resync_lock, - raid10_unplug(conf->mddev->queue)); - - /* block any new IO from starting */ - conf->barrier++; - - /* No wait for all pending IO to complete */ - wait_event_lock_irq(conf->wait_barrier, - !conf->nr_pending && conf->barrier < RESYNC_DEPTH, - conf->resync_lock, - raid10_unplug(conf->mddev->queue)); - - spin_unlock_irq(&conf->resync_lock); -} - -static void lower_barrier(conf_t *conf) -{ - unsigned long flags; - spin_lock_irqsave(&conf->resync_lock, flags); - conf->barrier--; - spin_unlock_irqrestore(&conf->resync_lock, flags); - wake_up(&conf->wait_barrier); -} - -static void wait_barrier(conf_t *conf) +static void device_barrier(conf_t *conf, sector_t sect) { spin_lock_irq(&conf->resync_lock); - if (conf->barrier) { - conf->nr_waiting++; - wait_event_lock_irq(conf->wait_barrier, !conf->barrier, - conf->resync_lock, - raid10_unplug(conf->mddev->queue)); - conf->nr_waiting--; + wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume), + conf->resync_lock, unplug_slaves(conf->mddev)); + + if (!conf->barrier++) { + wait_event_lock_irq(conf->wait_idle, !conf->nr_pending, + conf->resync_lock, unplug_slaves(conf->mddev)); + if (conf->nr_pending) + BUG(); } - conf->nr_pending++; - spin_unlock_irq(&conf->resync_lock); -} - -static void allow_barrier(conf_t *conf) -{ - unsigned long flags; - spin_lock_irqsave(&conf->resync_lock, flags); - conf->nr_pending--; - spin_unlock_irqrestore(&conf->resync_lock, flags); - wake_up(&conf->wait_barrier); -} - -static void freeze_array(conf_t *conf) -{ - /* stop syncio and normal IO and wait for everything to - * go quiet. - * We increment barrier and nr_waiting, and then - * wait until barrier+nr_pending match nr_queued+2 - */ - spin_lock_irq(&conf->resync_lock); - conf->barrier++; - conf->nr_waiting++; - wait_event_lock_irq(conf->wait_barrier, - conf->barrier+conf->nr_pending == conf->nr_queued+2, - conf->resync_lock, - raid10_unplug(conf->mddev->queue)); - spin_unlock_irq(&conf->resync_lock); -} - -static void unfreeze_array(conf_t *conf) -{ - /* reverse the effect of the freeze */ - spin_lock_irq(&conf->resync_lock); - conf->barrier--; - conf->nr_waiting--; - wake_up(&conf->wait_barrier); + wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH, + conf->resync_lock, unplug_slaves(conf->mddev)); + conf->next_resync = sect; spin_unlock_irq(&conf->resync_lock); } @@ -746,8 +674,6 @@ static int make_request(request_queue_t *q, struct bio * bio) int i; int chunk_sects = conf->chunk_mask + 1; const int rw = bio_data_dir(bio); - struct bio_list bl; - unsigned long flags; if (unlikely(bio_barrier(bio))) { bio_endio(bio, bio->bi_size, -EOPNOTSUPP); @@ -793,7 +719,10 @@ static int make_request(request_queue_t *q, struct bio * bio) * thread has put up a bar for new requests. * Continue immediately if no resync is active currently. */ - wait_barrier(conf); + spin_lock_irq(&conf->resync_lock); + wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, ); + conf->nr_pending++; + spin_unlock_irq(&conf->resync_lock); disk_stat_inc(mddev->gendisk, ios[rw]); disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); @@ -805,7 +734,6 @@ static int make_request(request_queue_t *q, struct bio * bio) r10_bio->mddev = mddev; r10_bio->sector = bio->bi_sector; - r10_bio->state = 0; if (rw == READ) { /* @@ -850,16 +778,13 @@ static int make_request(request_queue_t *q, struct bio * bio) !test_bit(Faulty, &rdev->flags)) { atomic_inc(&rdev->nr_pending); r10_bio->devs[i].bio = bio; - } else { + } else r10_bio->devs[i].bio = NULL; - set_bit(R10BIO_Degraded, &r10_bio->state); - } } rcu_read_unlock(); - atomic_set(&r10_bio->remaining, 0); + atomic_set(&r10_bio->remaining, 1); - bio_list_init(&bl); for (i = 0; i < conf->copies; i++) { struct bio *mbio; int d = r10_bio->devs[i].devnum; @@ -877,14 +802,13 @@ static int make_request(request_queue_t *q, struct bio * bio) mbio->bi_private = r10_bio; atomic_inc(&r10_bio->remaining); - bio_list_add(&bl, mbio); + generic_make_request(mbio); } - bitmap_startwrite(mddev->bitmap, bio->bi_sector, r10_bio->sectors, 0); - spin_lock_irqsave(&conf->device_lock, flags); - bio_list_merge(&conf->pending_bio_list, &bl); - blk_plug_device(mddev->queue); - spin_unlock_irqrestore(&conf->device_lock, flags); + if (atomic_dec_and_test(&r10_bio->remaining)) { + md_write_end(mddev); + raid_end_bio_io(r10_bio); + } return 0; } @@ -973,8 +897,13 @@ static void print_conf(conf_t *conf) static void close_sync(conf_t *conf) { - wait_barrier(conf); - allow_barrier(conf); + spin_lock_irq(&conf->resync_lock); + wait_event_lock_irq(conf->wait_resume, !conf->barrier, + conf->resync_lock, unplug_slaves(conf->mddev)); + spin_unlock_irq(&conf->resync_lock); + + if (conf->barrier) BUG(); + if (waitqueue_active(&conf->wait_idle)) BUG(); mempool_destroy(conf->r10buf_pool); conf->r10buf_pool = NULL; @@ -1042,12 +971,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) if (!enough(conf)) return 0; - if (rdev->saved_raid_disk >= 0 && - conf->mirrors[rdev->saved_raid_disk].rdev == NULL) - mirror = rdev->saved_raid_disk; - else - mirror = 0; - for ( ; mirror < mddev->raid_disks; mirror++) + for (mirror=0; mirror < mddev->raid_disks; mirror++) if ( !(p=conf->mirrors+mirror)->rdev) { blk_queue_stack_limits(mddev->queue, @@ -1063,8 +987,6 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) p->head_position = 0; rdev->raid_disk = mirror; found = 1; - if (rdev->saved_raid_disk != mirror) - conf->fullsync = 1; rcu_assign_pointer(p->rdev, rdev); break; } @@ -1105,6 +1027,7 @@ static int raid10_remove_disk(mddev_t *mddev, int number) static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) { + int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); conf_t *conf = mddev_to_conf(r10_bio->mddev); int i,d; @@ -1119,16 +1042,9 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) BUG(); update_head_pos(i, r10_bio); d = r10_bio->devs[i].devnum; - - if (test_bit(BIO_UPTODATE, &bio->bi_flags)) - set_bit(R10BIO_Uptodate, &r10_bio->state); - else { - atomic_add(r10_bio->sectors, - &conf->mirrors[d].rdev->corrected_errors); - if (!test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery)) - md_error(r10_bio->mddev, - conf->mirrors[d].rdev); - } + if (!uptodate) + md_error(r10_bio->mddev, + conf->mirrors[d].rdev); /* for reconstruct, we always reschedule after a read. * for resync, only after all reads @@ -1216,32 +1132,23 @@ static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio) fbio = r10_bio->devs[i].bio; /* now find blocks with errors */ - for (i=0 ; i < conf->copies ; i++) { - int j, d; - int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9); + for (i=first+1 ; i < conf->copies ; i++) { + int vcnt, j, d; - tbio = r10_bio->devs[i].bio; - - if (tbio->bi_end_io != end_sync_read) - continue; - if (i == first) + if (!test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags)) continue; - if (test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags)) { - /* We know that the bi_io_vec layout is the same for - * both 'first' and 'i', so we just compare them. - * All vec entries are PAGE_SIZE; - */ - for (j = 0; j < vcnt; j++) - if (memcmp(page_address(fbio->bi_io_vec[j].bv_page), - page_address(tbio->bi_io_vec[j].bv_page), - PAGE_SIZE)) - break; - if (j == vcnt) - continue; - mddev->resync_mismatches += r10_bio->sectors; - } - if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) - /* Don't fix anything. */ + /* We know that the bi_io_vec layout is the same for + * both 'first' and 'i', so we just compare them. + * All vec entries are PAGE_SIZE; + */ + tbio = r10_bio->devs[i].bio; + vcnt = r10_bio->sectors >> (PAGE_SHIFT-9); + for (j = 0; j < vcnt; j++) + if (memcmp(page_address(fbio->bi_io_vec[j].bv_page), + page_address(tbio->bi_io_vec[j].bv_page), + PAGE_SIZE)) + break; + if (j == vcnt) continue; /* Ok, we need to write this bio * First we need to fixup bv_offset, bv_len and @@ -1320,10 +1227,7 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio) atomic_inc(&conf->mirrors[d].rdev->nr_pending); md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9); - if (test_bit(R10BIO_Uptodate, &r10_bio->state)) - generic_make_request(wbio); - else - bio_endio(wbio, wbio->bi_size, -EIO); + generic_make_request(wbio); } @@ -1350,31 +1254,10 @@ static void raid10d(mddev_t *mddev) for (;;) { char b[BDEVNAME_SIZE]; spin_lock_irqsave(&conf->device_lock, flags); - - if (conf->pending_bio_list.head) { - bio = bio_list_get(&conf->pending_bio_list); - blk_remove_plug(mddev->queue); - spin_unlock_irqrestore(&conf->device_lock, flags); - /* flush any pending bitmap writes to disk before proceeding w/ I/O */ - if (bitmap_unplug(mddev->bitmap) != 0) - printk("%s: bitmap file write failed!\n", mdname(mddev)); - - while (bio) { /* submit pending writes */ - struct bio *next = bio->bi_next; - bio->bi_next = NULL; - generic_make_request(bio); - bio = next; - } - unplug = 1; - - continue; - } - if (list_empty(head)) break; r10_bio = list_entry(head->prev, r10bio_t, retry_list); list_del(head->prev); - conf->nr_queued--; spin_unlock_irqrestore(&conf->device_lock, flags); mddev = r10_bio->mddev; @@ -1387,96 +1270,8 @@ static void raid10d(mddev_t *mddev) unplug = 1; } else { int mirror; - /* we got a read error. Maybe the drive is bad. Maybe just - * the block and we can fix it. - * We freeze all other IO, and try reading the block from - * other devices. When we find one, we re-write - * and check it that fixes the read error. - * This is all done synchronously while the array is - * frozen. - */ - int sect = 0; /* Offset from r10_bio->sector */ - int sectors = r10_bio->sectors; - freeze_array(conf); - if (mddev->ro == 0) while(sectors) { - int s = sectors; - int sl = r10_bio->read_slot; - int success = 0; - - if (s > (PAGE_SIZE>>9)) - s = PAGE_SIZE >> 9; - - do { - int d = r10_bio->devs[sl].devnum; - rdev = conf->mirrors[d].rdev; - if (rdev && - test_bit(In_sync, &rdev->flags) && - sync_page_io(rdev->bdev, - r10_bio->devs[sl].addr + - sect + rdev->data_offset, - s<<9, - conf->tmppage, READ)) - success = 1; - else { - sl++; - if (sl == conf->copies) - sl = 0; - } - } while (!success && sl != r10_bio->read_slot); - - if (success) { - int start = sl; - /* write it back and re-read */ - while (sl != r10_bio->read_slot) { - int d; - if (sl==0) - sl = conf->copies; - sl--; - d = r10_bio->devs[sl].devnum; - rdev = conf->mirrors[d].rdev; - atomic_add(s, &rdev->corrected_errors); - if (rdev && - test_bit(In_sync, &rdev->flags)) { - if (sync_page_io(rdev->bdev, - r10_bio->devs[sl].addr + - sect + rdev->data_offset, - s<<9, conf->tmppage, WRITE) == 0) - /* Well, this device is dead */ - md_error(mddev, rdev); - } - } - sl = start; - while (sl != r10_bio->read_slot) { - int d; - if (sl==0) - sl = conf->copies; - sl--; - d = r10_bio->devs[sl].devnum; - rdev = conf->mirrors[d].rdev; - if (rdev && - test_bit(In_sync, &rdev->flags)) { - if (sync_page_io(rdev->bdev, - r10_bio->devs[sl].addr + - sect + rdev->data_offset, - s<<9, conf->tmppage, READ) == 0) - /* Well, this device is dead */ - md_error(mddev, rdev); - } - } - } else { - /* Cannot read from anywhere -- bye bye array */ - md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev); - break; - } - sectors -= s; - sect += s; - } - - unfreeze_array(conf); - bio = r10_bio->devs[r10_bio->read_slot].bio; - r10_bio->devs[r10_bio->read_slot].bio = - mddev->ro ? IO_BLOCKED : NULL; + r10_bio->devs[r10_bio->read_slot].bio = NULL; bio_put(bio); mirror = read_balance(conf, r10_bio); if (mirror == -1) { @@ -1565,8 +1360,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i sector_t max_sector, nr_sectors; int disk; int i; - int max_sync; - int sync_blocks; sector_t sectors_skipped = 0; int chunks_skipped = 0; @@ -1580,29 +1373,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) max_sector = mddev->resync_max_sectors; if (sector_nr >= max_sector) { - /* If we aborted, we need to abort the - * sync on the 'current' bitmap chucks (there can - * be several when recovering multiple devices). - * as we may have started syncing it but not finished. - * We can find the current address in - * mddev->curr_resync, but for recovery, - * we need to convert that to several - * virtual addresses. - */ - if (mddev->curr_resync < max_sector) { /* aborted */ - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) - bitmap_end_sync(mddev->bitmap, mddev->curr_resync, - &sync_blocks, 1); - else for (i=0; iraid_disks; i++) { - sector_t sect = - raid10_find_virt(conf, mddev->curr_resync, i); - bitmap_end_sync(mddev->bitmap, sect, - &sync_blocks, 1); - } - } else /* completed sync */ - conf->fullsync = 0; - - bitmap_close_sync(mddev->bitmap); close_sync(conf); *skipped = 1; return sectors_skipped; @@ -1625,8 +1395,9 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i * If there is non-resync activity waiting for us then * put in a delay to throttle resync. */ - if (!go_faster && conf->nr_waiting) + if (!go_faster && waitqueue_active(&conf->wait_resume)) msleep_interruptible(1000); + device_barrier(conf, sector_nr + RESYNC_SECTORS); /* Again, very different code for resync and recovery. * Both must result in an r10bio with a list of bios that @@ -1643,7 +1414,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i * end_sync_write if we will want to write. */ - max_sync = RESYNC_PAGES << (PAGE_SHIFT-9); if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { /* recovery... the complicated one */ int i, j, k; @@ -1652,29 +1422,14 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (i=0 ; iraid_disks; i++) if (conf->mirrors[i].rdev && !test_bit(In_sync, &conf->mirrors[i].rdev->flags)) { - int still_degraded = 0; /* want to reconstruct this device */ r10bio_t *rb2 = r10_bio; - sector_t sect = raid10_find_virt(conf, sector_nr, i); - int must_sync; - /* Unless we are doing a full sync, we only need - * to recover the block if it is set in the bitmap - */ - must_sync = bitmap_start_sync(mddev->bitmap, sect, - &sync_blocks, 1); - if (sync_blocks < max_sync) - max_sync = sync_blocks; - if (!must_sync && - !conf->fullsync) { - /* yep, skip the sync_blocks here, but don't assume - * that there will never be anything to do here - */ - chunks_skipped = -1; - continue; - } r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); - raise_barrier(conf, rb2 != NULL); + spin_lock_irq(&conf->resync_lock); + conf->nr_pending++; + if (rb2) conf->barrier++; + spin_unlock_irq(&conf->resync_lock); atomic_set(&r10_bio->remaining, 0); r10_bio->master_bio = (struct bio*)rb2; @@ -1682,23 +1437,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i atomic_inc(&rb2->remaining); r10_bio->mddev = mddev; set_bit(R10BIO_IsRecover, &r10_bio->state); - r10_bio->sector = sect; - + r10_bio->sector = raid10_find_virt(conf, sector_nr, i); raid10_find_phys(conf, r10_bio); - /* Need to check if this section will still be - * degraded - */ - for (j=0; jcopies;j++) { - int d = r10_bio->devs[j].devnum; - if (conf->mirrors[d].rdev == NULL || - test_bit(Faulty, &conf->mirrors[d].rdev->flags)) { - still_degraded = 1; - break; - } - } - must_sync = bitmap_start_sync(mddev->bitmap, sect, - &sync_blocks, still_degraded); - for (j=0; jcopies;j++) { int d = r10_bio->devs[j].devnum; if (conf->mirrors[d].rdev && @@ -1758,22 +1498,14 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i } else { /* resync. Schedule a read for every block at this virt offset */ int count = 0; - - if (!bitmap_start_sync(mddev->bitmap, sector_nr, - &sync_blocks, mddev->degraded) && - !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { - /* We can skip this block */ - *skipped = 1; - return sync_blocks + sectors_skipped; - } - if (sync_blocks < max_sync) - max_sync = sync_blocks; r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); + spin_lock_irq(&conf->resync_lock); + conf->nr_pending++; + spin_unlock_irq(&conf->resync_lock); + r10_bio->mddev = mddev; atomic_set(&r10_bio->remaining, 0); - raise_barrier(conf, 0); - conf->next_resync = sector_nr; r10_bio->master_bio = NULL; r10_bio->sector = sector_nr; @@ -1826,8 +1558,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i } nr_sectors = 0; - if (sector_nr + max_sync < max_sector) - max_sector = sector_nr + max_sync; do { struct page *page; int len = PAGE_SIZE; @@ -1902,11 +1632,11 @@ static int run(mddev_t *mddev) int nc, fc; sector_t stride, size; - if (mddev->chunk_size == 0) { - printk(KERN_ERR "md/raid10: non-zero chunk size required.\n"); - return -EINVAL; + if (mddev->level != 10) { + printk(KERN_ERR "raid10: %s: raid level not set correctly... (%d)\n", + mdname(mddev), mddev->level); + goto out; } - nc = mddev->layout & 255; fc = (mddev->layout >> 8) & 255; if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks || @@ -1920,24 +1650,22 @@ static int run(mddev_t *mddev) * bookkeeping area. [whatever we allocate in run(), * should be freed in stop()] */ - conf = kzalloc(sizeof(conf_t), GFP_KERNEL); + conf = kmalloc(sizeof(conf_t), GFP_KERNEL); mddev->private = conf; if (!conf) { printk(KERN_ERR "raid10: couldn't allocate memory for %s\n", mdname(mddev)); goto out; } - conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks, + memset(conf, 0, sizeof(*conf)); + conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks, GFP_KERNEL); if (!conf->mirrors) { printk(KERN_ERR "raid10: couldn't allocate memory for %s\n", mdname(mddev)); goto out_free_conf; } - - conf->tmppage = alloc_page(GFP_KERNEL); - if (!conf->tmppage) - goto out_free_conf; + memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks); conf->near_copies = nc; conf->far_copies = fc; @@ -1985,7 +1713,8 @@ static int run(mddev_t *mddev) INIT_LIST_HEAD(&conf->retry_list); spin_lock_init(&conf->resync_lock); - init_waitqueue_head(&conf->wait_barrier); + init_waitqueue_head(&conf->wait_idle); + init_waitqueue_head(&conf->wait_resume); /* need to check that every block has at least one working mirror */ if (!enough(conf)) { @@ -2034,7 +1763,7 @@ static int run(mddev_t *mddev) * maybe... */ { - int stripe = conf->raid_disks * mddev->chunk_size / PAGE_SIZE; + int stripe = conf->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE; stripe /= conf->near_copies; if (mddev->queue->backing_dev_info.ra_pages < 2* stripe) mddev->queue->backing_dev_info.ra_pages = 2* stripe; @@ -2047,7 +1776,6 @@ static int run(mddev_t *mddev) out_free_conf: if (conf->r10bio_pool) mempool_destroy(conf->r10bio_pool); - safe_put_page(conf->tmppage); kfree(conf->mirrors); kfree(conf); mddev->private = NULL; @@ -2070,31 +1798,10 @@ static int stop(mddev_t *mddev) return 0; } -static void raid10_quiesce(mddev_t *mddev, int state) -{ - conf_t *conf = mddev_to_conf(mddev); - - switch(state) { - case 1: - raise_barrier(conf, 0); - break; - case 0: - lower_barrier(conf); - break; - } - if (mddev->thread) { - if (mddev->bitmap) - mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; - else - mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; - md_wakeup_thread(mddev->thread); - } -} -static struct mdk_personality raid10_personality = +static mdk_personality_t raid10_personality = { .name = "raid10", - .level = 10, .owner = THIS_MODULE, .make_request = make_request, .run = run, @@ -2105,22 +1812,19 @@ static struct mdk_personality raid10_personality = .hot_remove_disk= raid10_remove_disk, .spare_active = raid10_spare_active, .sync_request = sync_request, - .quiesce = raid10_quiesce, }; static int __init raid_init(void) { - return register_md_personality(&raid10_personality); + return register_md_personality(RAID10, &raid10_personality); } static void raid_exit(void) { - unregister_md_personality(&raid10_personality); + unregister_md_personality(RAID10); } module_init(raid_init); module_exit(raid_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS("md-personality-9"); /* RAID10 */ -MODULE_ALIAS("md-raid10"); -MODULE_ALIAS("md-level-10"); diff --git a/trunk/drivers/md/raid5.c b/trunk/drivers/md/raid5.c index 54f4a9847e38..fafc4bc045f7 100644 --- a/trunk/drivers/md/raid5.c +++ b/trunk/drivers/md/raid5.c @@ -35,10 +35,12 @@ #define STRIPE_SHIFT (PAGE_SHIFT - 9) #define STRIPE_SECTORS (STRIPE_SIZE>>9) #define IO_THRESHOLD 1 -#define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head)) +#define HASH_PAGES 1 +#define HASH_PAGES_ORDER 0 +#define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *)) #define HASH_MASK (NR_HASH - 1) -#define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])) +#define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]) /* bio's attached to a stripe+device for I/O are linked together in bi_sector * order without overlap. There may be several bio's per stripe+device, and @@ -111,21 +113,29 @@ static void release_stripe(struct stripe_head *sh) spin_unlock_irqrestore(&conf->device_lock, flags); } -static inline void remove_hash(struct stripe_head *sh) +static void remove_hash(struct stripe_head *sh) { PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector); - hlist_del_init(&sh->hash); + if (sh->hash_pprev) { + if (sh->hash_next) + sh->hash_next->hash_pprev = sh->hash_pprev; + *sh->hash_pprev = sh->hash_next; + sh->hash_pprev = NULL; + } } -static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) +static __inline__ void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) { - struct hlist_head *hp = stripe_hash(conf, sh->sector); + struct stripe_head **shp = &stripe_hash(conf, sh->sector); PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector); CHECK_DEVLOCK(); - hlist_add_head(&sh->hash, hp); + if ((sh->hash_next = *shp) != NULL) + (*shp)->hash_pprev = &sh->hash_next; + *shp = sh; + sh->hash_pprev = shp; } @@ -157,7 +167,7 @@ static void shrink_buffers(struct stripe_head *sh, int num) if (!p) continue; sh->dev[i].page = NULL; - put_page(p); + page_cache_release(p); } } @@ -218,11 +228,10 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) { struct stripe_head *sh; - struct hlist_node *hn; CHECK_DEVLOCK(); PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); - hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash) + for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next) if (sh->sector == sector) return sh; PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); @@ -408,7 +417,7 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, set_bit(R5_UPTODATE, &sh->dev[i].flags); #endif if (test_bit(R5_ReadError, &sh->dev[i].flags)) { - printk(KERN_INFO "raid5: read error corrected!!\n"); + printk("R5: read error corrected!!\n"); clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); } @@ -419,14 +428,13 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, clear_bit(R5_UPTODATE, &sh->dev[i].flags); atomic_inc(&conf->disks[i].rdev->read_errors); if (conf->mddev->degraded) - printk(KERN_WARNING "raid5: read error not correctable.\n"); + printk("R5: read error not correctable.\n"); else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) /* Oh, no!!! */ - printk(KERN_WARNING "raid5: read error NOT corrected!!\n"); + printk("R5: read error NOT corrected!!\n"); else if (atomic_read(&conf->disks[i].rdev->read_errors) > conf->max_nr_stripes) - printk(KERN_WARNING - "raid5: Too many read errors, failing device.\n"); + printk("raid5: Too many read errors, failing device.\n"); else retry = 1; if (retry) @@ -596,7 +604,7 @@ static sector_t raid5_compute_sector(sector_t r_sector, unsigned int raid_disks, *dd_idx = (*pd_idx + 1 + *dd_idx) % raid_disks; break; default: - printk(KERN_ERR "raid5: unsupported algorithm %d\n", + printk("raid5: unsupported algorithm %d\n", conf->algorithm); } @@ -637,7 +645,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i) i -= (sh->pd_idx + 1); break; default: - printk(KERN_ERR "raid5: unsupported algorithm %d\n", + printk("raid5: unsupported algorithm %d\n", conf->algorithm); } @@ -646,7 +654,7 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i) check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf); if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) { - printk(KERN_ERR "compute_blocknr: map not correct\n"); + printk("compute_blocknr: map not correct\n"); return 0; } return r_sector; @@ -729,7 +737,7 @@ static void compute_block(struct stripe_head *sh, int dd_idx) if (test_bit(R5_UPTODATE, &sh->dev[i].flags)) ptr[count++] = p; else - printk(KERN_ERR "compute_block() %d, stripe %llu, %d" + printk("compute_block() %d, stripe %llu, %d" " not present\n", dd_idx, (unsigned long long)sh->sector, i); @@ -952,11 +960,11 @@ static void handle_stripe(struct stripe_head *sh) syncing = test_bit(STRIPE_SYNCING, &sh->state); /* Now to look around and see what can be done */ - rcu_read_lock(); for (i=disks; i--; ) { mdk_rdev_t *rdev; dev = &sh->dev[i]; clear_bit(R5_Insync, &dev->flags); + clear_bit(R5_Syncio, &dev->flags); PRINTK("check %d: state 0x%lx read %p write %p written %p\n", i, dev->flags, dev->toread, dev->towrite, dev->written); @@ -995,9 +1003,9 @@ static void handle_stripe(struct stripe_head *sh) non_overwrite++; } if (dev->written) written++; - rdev = rcu_dereference(conf->disks[i].rdev); + rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */ if (!rdev || !test_bit(In_sync, &rdev->flags)) { - /* The ReadError flag will just be confusing now */ + /* The ReadError flag wil just be confusing now */ clear_bit(R5_ReadError, &dev->flags); clear_bit(R5_ReWrite, &dev->flags); } @@ -1008,7 +1016,6 @@ static void handle_stripe(struct stripe_head *sh) } else set_bit(R5_Insync, &dev->flags); } - rcu_read_unlock(); PRINTK("locked=%d uptodate=%d to_read=%d" " to_write=%d failed=%d failed_num=%d\n", locked, uptodate, to_read, to_write, failed, failed_num); @@ -1020,13 +1027,10 @@ static void handle_stripe(struct stripe_head *sh) int bitmap_end = 0; if (test_bit(R5_ReadError, &sh->dev[i].flags)) { - mdk_rdev_t *rdev; - rcu_read_lock(); - rdev = rcu_dereference(conf->disks[i].rdev); + mdk_rdev_t *rdev = conf->disks[i].rdev; if (rdev && test_bit(In_sync, &rdev->flags)) /* multiple read failures in one stripe */ md_error(conf->mddev, rdev); - rcu_read_unlock(); } spin_lock_irq(&conf->device_lock); @@ -1175,6 +1179,9 @@ static void handle_stripe(struct stripe_head *sh) locked++; PRINTK("Reading block %d (sync=%d)\n", i, syncing); + if (syncing) + md_sync_acct(conf->disks[i].rdev->bdev, + STRIPE_SECTORS); } } } @@ -1281,7 +1288,7 @@ static void handle_stripe(struct stripe_head *sh) * is available */ if (syncing && locked == 0 && - !test_bit(STRIPE_INSYNC, &sh->state)) { + !test_bit(STRIPE_INSYNC, &sh->state) && failed <= 1) { set_bit(STRIPE_HANDLE, &sh->state); if (failed == 0) { char *pagea; @@ -1299,25 +1306,27 @@ static void handle_stripe(struct stripe_head *sh) if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) /* don't try to repair!! */ set_bit(STRIPE_INSYNC, &sh->state); - else { - compute_block(sh, sh->pd_idx); - uptodate++; - } } } if (!test_bit(STRIPE_INSYNC, &sh->state)) { - /* either failed parity check, or recovery is happening */ if (failed==0) failed_num = sh->pd_idx; + /* should be able to compute the missing block and write it to spare */ + if (!test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)) { + if (uptodate+1 != disks) + BUG(); + compute_block(sh, failed_num); + uptodate++; + } + if (uptodate != disks) + BUG(); dev = &sh->dev[failed_num]; - BUG_ON(!test_bit(R5_UPTODATE, &dev->flags)); - BUG_ON(uptodate != disks); - set_bit(R5_LOCKED, &dev->flags); set_bit(R5_Wantwrite, &dev->flags); clear_bit(STRIPE_DEGRADED, &sh->state); locked++; set_bit(STRIPE_INSYNC, &sh->state); + set_bit(R5_Syncio, &dev->flags); } } if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) { @@ -1383,7 +1392,7 @@ static void handle_stripe(struct stripe_head *sh) rcu_read_unlock(); if (rdev) { - if (syncing) + if (test_bit(R5_Syncio, &sh->dev[i].flags)) md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; @@ -1400,9 +1409,6 @@ static void handle_stripe(struct stripe_head *sh) bi->bi_io_vec[0].bv_offset = 0; bi->bi_size = STRIPE_SIZE; bi->bi_next = NULL; - if (rw == WRITE && - test_bit(R5_ReWrite, &sh->dev[i].flags)) - atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); generic_make_request(bi); } else { if (rw == 1) @@ -1816,21 +1822,21 @@ static int run(mddev_t *mddev) struct list_head *tmp; if (mddev->level != 5 && mddev->level != 4) { - printk(KERN_ERR "raid5: %s: raid level not set to 4/5 (%d)\n", - mdname(mddev), mddev->level); + printk("raid5: %s: raid level not set to 4/5 (%d)\n", mdname(mddev), mddev->level); return -EIO; } - mddev->private = kzalloc(sizeof (raid5_conf_t) - + mddev->raid_disks * sizeof(struct disk_info), - GFP_KERNEL); + mddev->private = kmalloc (sizeof (raid5_conf_t) + + mddev->raid_disks * sizeof(struct disk_info), + GFP_KERNEL); if ((conf = mddev->private) == NULL) goto abort; - + memset (conf, 0, sizeof (*conf) + mddev->raid_disks * sizeof(struct disk_info) ); conf->mddev = mddev; - if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL) + if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) goto abort; + memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); spin_lock_init(&conf->device_lock); init_waitqueue_head(&conf->wait_for_stripe); @@ -1897,17 +1903,10 @@ static int run(mddev_t *mddev) if (mddev->degraded == 1 && mddev->recovery_cp != MaxSector) { - if (mddev->ok_start_degraded) - printk(KERN_WARNING - "raid5: starting dirty degraded array: %s" - "- data corruption possible.\n", - mdname(mddev)); - else { - printk(KERN_ERR - "raid5: cannot start dirty degraded array for %s\n", - mdname(mddev)); - goto abort; - } + printk(KERN_ERR + "raid5: cannot start dirty degraded array for %s\n", + mdname(mddev)); + goto abort; } { @@ -1949,7 +1948,7 @@ static int run(mddev_t *mddev) */ { int stripe = (mddev->raid_disks-1) * mddev->chunk_size - / PAGE_SIZE; + / PAGE_CACHE_SIZE; if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe) mddev->queue->backing_dev_info.ra_pages = 2 * stripe; } @@ -1957,6 +1956,9 @@ static int run(mddev_t *mddev) /* Ok, everything is just fine now */ sysfs_create_group(&mddev->kobj, &raid5_attrs_group); + if (mddev->bitmap) + mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; + mddev->queue->unplug_fn = raid5_unplug_device; mddev->queue->issue_flush_fn = raid5_issue_flush; @@ -1965,7 +1967,9 @@ static int run(mddev_t *mddev) abort: if (conf) { print_raid5_conf(conf); - kfree(conf->stripe_hashtbl); + if (conf->stripe_hashtbl) + free_pages((unsigned long) conf->stripe_hashtbl, + HASH_PAGES_ORDER); kfree(conf); } mddev->private = NULL; @@ -1982,7 +1986,7 @@ static int stop(mddev_t *mddev) md_unregister_thread(mddev->thread); mddev->thread = NULL; shrink_stripes(conf); - kfree(conf->stripe_hashtbl); + free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); kfree(conf); @@ -2010,12 +2014,12 @@ static void print_sh (struct stripe_head *sh) static void printall (raid5_conf_t *conf) { struct stripe_head *sh; - struct hlist_node *hn; int i; spin_lock_irq(&conf->device_lock); for (i = 0; i < NR_HASH; i++) { - hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) { + sh = conf->stripe_hashtbl[i]; + for (; sh; sh = sh->hash_next) { if (sh->raid_conf != conf) continue; print_sh(sh); @@ -2188,12 +2192,17 @@ static void raid5_quiesce(mddev_t *mddev, int state) spin_unlock_irq(&conf->device_lock); break; } + if (mddev->thread) { + if (mddev->bitmap) + mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; + else + mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; + md_wakeup_thread(mddev->thread); + } } - -static struct mdk_personality raid5_personality = +static mdk_personality_t raid5_personality= { .name = "raid5", - .level = 5, .owner = THIS_MODULE, .make_request = make_request, .run = run, @@ -2208,42 +2217,17 @@ static struct mdk_personality raid5_personality = .quiesce = raid5_quiesce, }; -static struct mdk_personality raid4_personality = +static int __init raid5_init (void) { - .name = "raid4", - .level = 4, - .owner = THIS_MODULE, - .make_request = make_request, - .run = run, - .stop = stop, - .status = status, - .error_handler = error, - .hot_add_disk = raid5_add_disk, - .hot_remove_disk= raid5_remove_disk, - .spare_active = raid5_spare_active, - .sync_request = sync_request, - .resize = raid5_resize, - .quiesce = raid5_quiesce, -}; - -static int __init raid5_init(void) -{ - register_md_personality(&raid5_personality); - register_md_personality(&raid4_personality); - return 0; + return register_md_personality (RAID5, &raid5_personality); } -static void raid5_exit(void) +static void raid5_exit (void) { - unregister_md_personality(&raid5_personality); - unregister_md_personality(&raid4_personality); + unregister_md_personality (RAID5); } module_init(raid5_init); module_exit(raid5_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS("md-personality-4"); /* RAID5 */ -MODULE_ALIAS("md-raid5"); -MODULE_ALIAS("md-raid4"); -MODULE_ALIAS("md-level-5"); -MODULE_ALIAS("md-level-4"); diff --git a/trunk/drivers/md/raid6main.c b/trunk/drivers/md/raid6main.c index 8c823d686a60..0000d162d198 100644 --- a/trunk/drivers/md/raid6main.c +++ b/trunk/drivers/md/raid6main.c @@ -40,10 +40,12 @@ #define STRIPE_SHIFT (PAGE_SHIFT - 9) #define STRIPE_SECTORS (STRIPE_SIZE>>9) #define IO_THRESHOLD 1 -#define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head)) +#define HASH_PAGES 1 +#define HASH_PAGES_ORDER 0 +#define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *)) #define HASH_MASK (NR_HASH - 1) -#define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])) +#define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]) /* bio's attached to a stripe+device for I/O are linked together in bi_sector * order without overlap. There may be several bio's per stripe+device, and @@ -130,21 +132,29 @@ static void release_stripe(struct stripe_head *sh) spin_unlock_irqrestore(&conf->device_lock, flags); } -static inline void remove_hash(struct stripe_head *sh) +static void remove_hash(struct stripe_head *sh) { PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector); - hlist_del_init(&sh->hash); + if (sh->hash_pprev) { + if (sh->hash_next) + sh->hash_next->hash_pprev = sh->hash_pprev; + *sh->hash_pprev = sh->hash_next; + sh->hash_pprev = NULL; + } } -static inline void insert_hash(raid6_conf_t *conf, struct stripe_head *sh) +static __inline__ void insert_hash(raid6_conf_t *conf, struct stripe_head *sh) { - struct hlist_head *hp = stripe_hash(conf, sh->sector); + struct stripe_head **shp = &stripe_hash(conf, sh->sector); PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector); CHECK_DEVLOCK(); - hlist_add_head(&sh->hash, hp); + if ((sh->hash_next = *shp) != NULL) + (*shp)->hash_pprev = &sh->hash_next; + *shp = sh; + sh->hash_pprev = shp; } @@ -176,7 +186,7 @@ static void shrink_buffers(struct stripe_head *sh, int num) if (!p) continue; sh->dev[i].page = NULL; - put_page(p); + page_cache_release(p); } } @@ -237,11 +247,10 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i static struct stripe_head *__find_stripe(raid6_conf_t *conf, sector_t sector) { struct stripe_head *sh; - struct hlist_node *hn; CHECK_DEVLOCK(); PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); - hlist_for_each_entry (sh, hn, stripe_hash(conf, sector), hash) + for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next) if (sh->sector == sector) return sh; PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); @@ -358,8 +367,8 @@ static void shrink_stripes(raid6_conf_t *conf) conf->slab_cache = NULL; } -static int raid6_end_read_request(struct bio * bi, unsigned int bytes_done, - int error) +static int raid6_end_read_request (struct bio * bi, unsigned int bytes_done, + int error) { struct stripe_head *sh = bi->bi_private; raid6_conf_t *conf = sh->raid_conf; @@ -411,35 +420,9 @@ static int raid6_end_read_request(struct bio * bi, unsigned int bytes_done, #else set_bit(R5_UPTODATE, &sh->dev[i].flags); #endif - if (test_bit(R5_ReadError, &sh->dev[i].flags)) { - printk(KERN_INFO "raid6: read error corrected!!\n"); - clear_bit(R5_ReadError, &sh->dev[i].flags); - clear_bit(R5_ReWrite, &sh->dev[i].flags); - } - if (atomic_read(&conf->disks[i].rdev->read_errors)) - atomic_set(&conf->disks[i].rdev->read_errors, 0); } else { - int retry = 0; + md_error(conf->mddev, conf->disks[i].rdev); clear_bit(R5_UPTODATE, &sh->dev[i].flags); - atomic_inc(&conf->disks[i].rdev->read_errors); - if (conf->mddev->degraded) - printk(KERN_WARNING "raid6: read error not correctable.\n"); - else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) - /* Oh, no!!! */ - printk(KERN_WARNING "raid6: read error NOT corrected!!\n"); - else if (atomic_read(&conf->disks[i].rdev->read_errors) - > conf->max_nr_stripes) - printk(KERN_WARNING - "raid6: Too many read errors, failing device.\n"); - else - retry = 1; - if (retry) - set_bit(R5_ReadError, &sh->dev[i].flags); - else { - clear_bit(R5_ReadError, &sh->dev[i].flags); - clear_bit(R5_ReWrite, &sh->dev[i].flags); - md_error(conf->mddev, conf->disks[i].rdev); - } } rdev_dec_pending(conf->disks[i].rdev, conf->mddev); #if 0 @@ -822,7 +805,7 @@ static void compute_parity(struct stripe_head *sh, int method) } /* Compute one missing block */ -static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) +static void compute_block_1(struct stripe_head *sh, int dd_idx) { raid6_conf_t *conf = sh->raid_conf; int i, count, disks = conf->raid_disks; @@ -838,7 +821,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) compute_parity(sh, UPDATE_PARITY); } else { ptr[0] = page_address(sh->dev[dd_idx].page); - if (!nozero) memset(ptr[0], 0, STRIPE_SIZE); + memset(ptr[0], 0, STRIPE_SIZE); count = 1; for (i = disks ; i--; ) { if (i == dd_idx || i == qd_idx) @@ -855,8 +838,7 @@ static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero) } if (count != 1) xor_block(count, STRIPE_SIZE, ptr); - if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); - else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); + set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags); } } @@ -889,7 +871,7 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) return; } else { /* We're missing D+Q; recompute D from P */ - compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0); + compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1); compute_parity(sh, UPDATE_PARITY); /* Is this necessary? */ return; } @@ -1000,12 +982,6 @@ static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, in } -static int page_is_zero(struct page *p) -{ - char *a = page_address(p); - return ((*(u32*)a) == 0 && - memcmp(a, a+4, STRIPE_SIZE-4)==0); -} /* * handle_stripe - do things to a stripe. * @@ -1024,7 +1000,7 @@ static int page_is_zero(struct page *p) * */ -static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) +static void handle_stripe(struct stripe_head *sh) { raid6_conf_t *conf = sh->raid_conf; int disks = conf->raid_disks; @@ -1051,11 +1027,11 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) syncing = test_bit(STRIPE_SYNCING, &sh->state); /* Now to look around and see what can be done */ - rcu_read_lock(); for (i=disks; i--; ) { mdk_rdev_t *rdev; dev = &sh->dev[i]; clear_bit(R5_Insync, &dev->flags); + clear_bit(R5_Syncio, &dev->flags); PRINTK("check %d: state 0x%lx read %p write %p written %p\n", i, dev->flags, dev->toread, dev->towrite, dev->written); @@ -1094,21 +1070,14 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) non_overwrite++; } if (dev->written) written++; - rdev = rcu_dereference(conf->disks[i].rdev); + rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */ if (!rdev || !test_bit(In_sync, &rdev->flags)) { - /* The ReadError flag will just be confusing now */ - clear_bit(R5_ReadError, &dev->flags); - clear_bit(R5_ReWrite, &dev->flags); - } - if (!rdev || !test_bit(In_sync, &rdev->flags) - || test_bit(R5_ReadError, &dev->flags)) { if ( failed < 2 ) failed_num[failed] = i; failed++; } else set_bit(R5_Insync, &dev->flags); } - rcu_read_unlock(); PRINTK("locked=%d uptodate=%d to_read=%d" " to_write=%d failed=%d failed_num=%d,%d\n", locked, uptodate, to_read, to_write, failed, @@ -1119,17 +1088,6 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) if (failed > 2 && to_read+to_write+written) { for (i=disks; i--; ) { int bitmap_end = 0; - - if (test_bit(R5_ReadError, &sh->dev[i].flags)) { - mdk_rdev_t *rdev; - rcu_read_lock(); - rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && test_bit(In_sync, &rdev->flags)) - /* multiple read failures in one stripe */ - md_error(conf->mddev, rdev); - rcu_read_unlock(); - } - spin_lock_irq(&conf->device_lock); /* fail all writes first */ bi = sh->dev[i].towrite; @@ -1165,8 +1123,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) } /* fail any reads if this device is non-operational */ - if (!test_bit(R5_Insync, &sh->dev[i].flags) || - test_bit(R5_ReadError, &sh->dev[i].flags)) { + if (!test_bit(R5_Insync, &sh->dev[i].flags)) { bi = sh->dev[i].toread; sh->dev[i].toread = NULL; if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) @@ -1271,7 +1228,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) if (uptodate == disks-1) { PRINTK("Computing stripe %llu block %d\n", (unsigned long long)sh->sector, i); - compute_block_1(sh, i, 0); + compute_block_1(sh, i); uptodate++; } else if ( uptodate == disks-2 && failed >= 2 ) { /* Computing 2-failure is *very* expensive; only do it if failed >= 2 */ @@ -1302,6 +1259,9 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) locked++; PRINTK("Reading block %d (sync=%d)\n", i, syncing); + if (syncing) + md_sync_acct(conf->disks[i].rdev->bdev, + STRIPE_SECTORS); } } } @@ -1363,7 +1323,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) /* We have failed blocks and need to compute them */ switch ( failed ) { case 0: BUG(); - case 1: compute_block_1(sh, failed_num[0], 0); break; + case 1: compute_block_1(sh, failed_num[0]); break; case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break; default: BUG(); /* This request should have been failed? */ } @@ -1378,10 +1338,12 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) (unsigned long long)sh->sector, i); locked++; set_bit(R5_Wantwrite, &sh->dev[i].flags); +#if 0 /**** FIX: I don't understand the logic here... ****/ + if (!test_bit(R5_Insync, &sh->dev[i].flags) + || ((i==pd_idx || i==qd_idx) && failed == 0)) /* FIX? */ + set_bit(STRIPE_INSYNC, &sh->state); +#endif } - /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */ - set_bit(STRIPE_INSYNC, &sh->state); - if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { atomic_dec(&conf->preread_active_stripes); if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) @@ -1394,119 +1356,84 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) * Any reads will already have been scheduled, so we just see if enough data * is available */ - if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) { - int update_p = 0, update_q = 0; - struct r5dev *dev; - + if (syncing && locked == 0 && + !test_bit(STRIPE_INSYNC, &sh->state) && failed <= 2) { set_bit(STRIPE_HANDLE, &sh->state); +#if 0 /* RAID-6: Don't support CHECK PARITY yet */ + if (failed == 0) { + char *pagea; + if (uptodate != disks) + BUG(); + compute_parity(sh, CHECK_PARITY); + uptodate--; + pagea = page_address(sh->dev[pd_idx].page); + if ((*(u32*)pagea) == 0 && + !memcmp(pagea, pagea+4, STRIPE_SIZE-4)) { + /* parity is correct (on disc, not in buffer any more) */ + set_bit(STRIPE_INSYNC, &sh->state); + } + } +#endif + if (!test_bit(STRIPE_INSYNC, &sh->state)) { + int failed_needupdate[2]; + struct r5dev *adev, *bdev; - BUG_ON(failed>2); - BUG_ON(uptodate < disks); - /* Want to check and possibly repair P and Q. - * However there could be one 'failed' device, in which - * case we can only check one of them, possibly using the - * other to generate missing data - */ + if ( failed < 1 ) + failed_num[0] = pd_idx; + if ( failed < 2 ) + failed_num[1] = (failed_num[0] == qd_idx) ? pd_idx : qd_idx; - /* If !tmp_page, we cannot do the calculations, - * but as we have set STRIPE_HANDLE, we will soon be called - * by stripe_handle with a tmp_page - just wait until then. - */ - if (tmp_page) { - if (failed == q_failed) { - /* The only possible failed device holds 'Q', so it makes - * sense to check P (If anything else were failed, we would - * have used P to recreate it). - */ - compute_block_1(sh, pd_idx, 1); - if (!page_is_zero(sh->dev[pd_idx].page)) { - compute_block_1(sh,pd_idx,0); - update_p = 1; - } - } - if (!q_failed && failed < 2) { - /* q is not failed, and we didn't use it to generate - * anything, so it makes sense to check it - */ - memcpy(page_address(tmp_page), - page_address(sh->dev[qd_idx].page), - STRIPE_SIZE); - compute_parity(sh, UPDATE_PARITY); - if (memcmp(page_address(tmp_page), - page_address(sh->dev[qd_idx].page), - STRIPE_SIZE)!= 0) { - clear_bit(STRIPE_INSYNC, &sh->state); - update_q = 1; - } - } - if (update_p || update_q) { - conf->mddev->resync_mismatches += STRIPE_SECTORS; - if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) - /* don't try to repair!! */ - update_p = update_q = 0; - } + failed_needupdate[0] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[0]].flags); + failed_needupdate[1] = !test_bit(R5_UPTODATE, &sh->dev[failed_num[1]].flags); - /* now write out any block on a failed drive, - * or P or Q if they need it - */ + PRINTK("sync: failed=%d num=%d,%d fnu=%u%u\n", + failed, failed_num[0], failed_num[1], failed_needupdate[0], failed_needupdate[1]); - if (failed == 2) { - dev = &sh->dev[failed_num[1]]; - locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); - } - if (failed >= 1) { - dev = &sh->dev[failed_num[0]]; - locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); +#if 0 /* RAID-6: This code seems to require that CHECK_PARITY destroys the uptodateness of the parity */ + /* should be able to compute the missing block(s) and write to spare */ + if ( failed_needupdate[0] ^ failed_needupdate[1] ) { + if (uptodate+1 != disks) + BUG(); + compute_block_1(sh, failed_needupdate[0] ? failed_num[0] : failed_num[1]); + uptodate++; + } else if ( failed_needupdate[0] & failed_needupdate[1] ) { + if (uptodate+2 != disks) + BUG(); + compute_block_2(sh, failed_num[0], failed_num[1]); + uptodate += 2; } +#else + compute_block_2(sh, failed_num[0], failed_num[1]); + uptodate += failed_needupdate[0] + failed_needupdate[1]; +#endif - if (update_p) { - dev = &sh->dev[pd_idx]; - locked ++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); - } - if (update_q) { - dev = &sh->dev[qd_idx]; - locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); - } + if (uptodate != disks) + BUG(); + + PRINTK("Marking for sync stripe %llu blocks %d,%d\n", + (unsigned long long)sh->sector, failed_num[0], failed_num[1]); + + /**** FIX: Should we really do both of these unconditionally? ****/ + adev = &sh->dev[failed_num[0]]; + locked += !test_bit(R5_LOCKED, &adev->flags); + set_bit(R5_LOCKED, &adev->flags); + set_bit(R5_Wantwrite, &adev->flags); + bdev = &sh->dev[failed_num[1]]; + locked += !test_bit(R5_LOCKED, &bdev->flags); + set_bit(R5_LOCKED, &bdev->flags); clear_bit(STRIPE_DEGRADED, &sh->state); + set_bit(R5_Wantwrite, &bdev->flags); set_bit(STRIPE_INSYNC, &sh->state); + set_bit(R5_Syncio, &adev->flags); + set_bit(R5_Syncio, &bdev->flags); } } - if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) { md_done_sync(conf->mddev, STRIPE_SECTORS,1); clear_bit(STRIPE_SYNCING, &sh->state); } - /* If the failed drives are just a ReadError, then we might need - * to progress the repair/check process - */ - if (failed <= 2 && ! conf->mddev->ro) - for (i=0; idev[failed_num[i]]; - if (test_bit(R5_ReadError, &dev->flags) - && !test_bit(R5_LOCKED, &dev->flags) - && test_bit(R5_UPTODATE, &dev->flags) - ) { - if (!test_bit(R5_ReWrite, &dev->flags)) { - set_bit(R5_Wantwrite, &dev->flags); - set_bit(R5_ReWrite, &dev->flags); - set_bit(R5_LOCKED, &dev->flags); - } else { - /* let's read it back */ - set_bit(R5_Wantread, &dev->flags); - set_bit(R5_LOCKED, &dev->flags); - } - } - } spin_unlock(&sh->lock); while ((bi=return_bi)) { @@ -1545,7 +1472,7 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) rcu_read_unlock(); if (rdev) { - if (syncing) + if (test_bit(R5_Syncio, &sh->dev[i].flags)) md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; @@ -1562,9 +1489,6 @@ static void handle_stripe(struct stripe_head *sh, struct page *tmp_page) bi->bi_io_vec[0].bv_offset = 0; bi->bi_size = STRIPE_SIZE; bi->bi_next = NULL; - if (rw == WRITE && - test_bit(R5_ReWrite, &sh->dev[i].flags)) - atomic_add(STRIPE_SECTORS, &rdev->corrected_errors); generic_make_request(bi); } else { if (rw == 1) @@ -1740,7 +1664,7 @@ static int make_request (request_queue_t *q, struct bio * bi) } finish_wait(&conf->wait_for_overlap, &w); raid6_plug_device(conf); - handle_stripe(sh, NULL); + handle_stripe(sh); release_stripe(sh); } else { /* cannot get stripe for read-ahead, just give-up */ @@ -1804,7 +1728,6 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i return rv; } if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) && - !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) && !conf->fullsync && sync_blocks >= STRIPE_SECTORS) { /* we can skip this block, and probably more */ sync_blocks /= STRIPE_SECTORS; @@ -1842,7 +1765,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i clear_bit(STRIPE_INSYNC, &sh->state); spin_unlock(&sh->lock); - handle_stripe(sh, NULL); + handle_stripe(sh); release_stripe(sh); return STRIPE_SECTORS; @@ -1898,7 +1821,7 @@ static void raid6d (mddev_t *mddev) spin_unlock_irq(&conf->device_lock); handled++; - handle_stripe(sh, conf->spare_page); + handle_stripe(sh); release_stripe(sh); spin_lock_irq(&conf->device_lock); @@ -1925,19 +1848,17 @@ static int run(mddev_t *mddev) return -EIO; } - mddev->private = kzalloc(sizeof (raid6_conf_t) - + mddev->raid_disks * sizeof(struct disk_info), - GFP_KERNEL); + mddev->private = kmalloc (sizeof (raid6_conf_t) + + mddev->raid_disks * sizeof(struct disk_info), + GFP_KERNEL); if ((conf = mddev->private) == NULL) goto abort; + memset (conf, 0, sizeof (*conf) + mddev->raid_disks * sizeof(struct disk_info) ); conf->mddev = mddev; - if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL) - goto abort; - - conf->spare_page = alloc_page(GFP_KERNEL); - if (!conf->spare_page) + if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) goto abort; + memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); spin_lock_init(&conf->device_lock); init_waitqueue_head(&conf->wait_for_stripe); @@ -2008,18 +1929,13 @@ static int run(mddev_t *mddev) goto abort; } +#if 0 /* FIX: For now */ if (mddev->degraded > 0 && mddev->recovery_cp != MaxSector) { - if (mddev->ok_start_degraded) - printk(KERN_WARNING "raid6: starting dirty degraded array:%s" - "- data corruption possible.\n", - mdname(mddev)); - else { - printk(KERN_ERR "raid6: cannot start dirty degraded array" - " for %s\n", mdname(mddev)); - goto abort; - } + printk(KERN_ERR "raid6: cannot start dirty degraded array for %s\n", mdname(mddev)); + goto abort; } +#endif { mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6"); @@ -2061,7 +1977,7 @@ static int run(mddev_t *mddev) */ { int stripe = (mddev->raid_disks-2) * mddev->chunk_size - / PAGE_SIZE; + / PAGE_CACHE_SIZE; if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe) mddev->queue->backing_dev_info.ra_pages = 2 * stripe; } @@ -2069,14 +1985,18 @@ static int run(mddev_t *mddev) /* Ok, everything is just fine now */ mddev->array_size = mddev->size * (mddev->raid_disks - 2); + if (mddev->bitmap) + mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; + mddev->queue->unplug_fn = raid6_unplug_device; mddev->queue->issue_flush_fn = raid6_issue_flush; return 0; abort: if (conf) { print_raid6_conf(conf); - safe_put_page(conf->spare_page); - kfree(conf->stripe_hashtbl); + if (conf->stripe_hashtbl) + free_pages((unsigned long) conf->stripe_hashtbl, + HASH_PAGES_ORDER); kfree(conf); } mddev->private = NULL; @@ -2093,7 +2013,7 @@ static int stop (mddev_t *mddev) md_unregister_thread(mddev->thread); mddev->thread = NULL; shrink_stripes(conf); - kfree(conf->stripe_hashtbl); + free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ kfree(conf); mddev->private = NULL; @@ -2120,13 +2040,12 @@ static void print_sh (struct seq_file *seq, struct stripe_head *sh) static void printall (struct seq_file *seq, raid6_conf_t *conf) { struct stripe_head *sh; - struct hlist_node *hn; int i; spin_lock_irq(&conf->device_lock); for (i = 0; i < NR_HASH; i++) { sh = conf->stripe_hashtbl[i]; - hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) { + for (; sh; sh = sh->hash_next) { if (sh->raid_conf != conf) continue; print_sh(seq, sh); @@ -2304,12 +2223,17 @@ static void raid6_quiesce(mddev_t *mddev, int state) spin_unlock_irq(&conf->device_lock); break; } + if (mddev->thread) { + if (mddev->bitmap) + mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; + else + mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT; + md_wakeup_thread(mddev->thread); + } } - -static struct mdk_personality raid6_personality = +static mdk_personality_t raid6_personality= { .name = "raid6", - .level = 6, .owner = THIS_MODULE, .make_request = make_request, .run = run, @@ -2324,7 +2248,7 @@ static struct mdk_personality raid6_personality = .quiesce = raid6_quiesce, }; -static int __init raid6_init(void) +static int __init raid6_init (void) { int e; @@ -2332,17 +2256,15 @@ static int __init raid6_init(void) if ( e ) return e; - return register_md_personality(&raid6_personality); + return register_md_personality (RAID6, &raid6_personality); } static void raid6_exit (void) { - unregister_md_personality(&raid6_personality); + unregister_md_personality (RAID6); } module_init(raid6_init); module_exit(raid6_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS("md-personality-8"); /* RAID6 */ -MODULE_ALIAS("md-raid6"); -MODULE_ALIAS("md-level-6"); diff --git a/trunk/drivers/media/video/cpia_pp.c b/trunk/drivers/media/video/cpia_pp.c index 6861d408f1b3..ddf184f95d80 100644 --- a/trunk/drivers/media/video/cpia_pp.c +++ b/trunk/drivers/media/video/cpia_pp.c @@ -170,9 +170,16 @@ static size_t cpia_read_nibble (struct parport *port, /* Does the error line indicate end of data? */ if (((i /*& 1*/) == 0) && (parport_read_status(port) & PARPORT_STATUS_ERROR)) { - DBG("%s: No more nibble data (%d bytes)\n", - port->name, i/2); - goto end_of_data; + port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; + DBG("%s: No more nibble data (%d bytes)\n", + port->name, i/2); + + /* Go to reverse idle phase. */ + parport_frob_control (port, + PARPORT_CONTROL_AUTOFD, + PARPORT_CONTROL_AUTOFD); + port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; + break; } /* Event 7: Set nAutoFd low. */ @@ -220,21 +227,18 @@ static size_t cpia_read_nibble (struct parport *port, byte = nibble; } + i /= 2; /* i is now in bytes */ + if (i == len) { /* Read the last nibble without checking data avail. */ - if (parport_read_status (port) & PARPORT_STATUS_ERROR) { - end_of_data: - /* Go to reverse idle phase. */ - parport_frob_control (port, - PARPORT_CONTROL_AUTOFD, - PARPORT_CONTROL_AUTOFD); - port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; - } + port = port->physport; + if (parport_read_status (port) & PARPORT_STATUS_ERROR) + port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; else - port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL; + port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL; } - return i/2; + return i; } /* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1) diff --git a/trunk/drivers/message/i2o/Kconfig b/trunk/drivers/message/i2o/Kconfig index fef677103880..43a942a29c2e 100644 --- a/trunk/drivers/message/i2o/Kconfig +++ b/trunk/drivers/message/i2o/Kconfig @@ -24,18 +24,6 @@ config I2O If unsure, say N. -config I2O_LCT_NOTIFY_ON_CHANGES - bool "Enable LCT notification" - depends on I2O - default y - ---help--- - Only say N here if you have a I2O controller from SUN. The SUN - firmware doesn't support LCT notification on changes. If this option - is enabled on such a controller the driver will hang up in a endless - loop. On all other controllers say Y. - - If unsure, say Y. - config I2O_EXT_ADAPTEC bool "Enable Adaptec extensions" depends on I2O diff --git a/trunk/drivers/message/i2o/bus-osm.c b/trunk/drivers/message/i2o/bus-osm.c index ac06f10c54ec..151b228e1cb3 100644 --- a/trunk/drivers/message/i2o/bus-osm.c +++ b/trunk/drivers/message/i2o/bus-osm.c @@ -17,7 +17,7 @@ #include #define OSM_NAME "bus-osm" -#define OSM_VERSION "1.317" +#define OSM_VERSION "$Rev$" #define OSM_DESCRIPTION "I2O Bus Adapter OSM" static struct i2o_driver i2o_bus_driver; @@ -39,18 +39,18 @@ static struct i2o_class_id i2o_bus_class_id[] = { */ static int i2o_bus_scan(struct i2o_device *dev) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data. - tid); + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); - return i2o_msg_post_wait(dev->iop, msg, 60); + return i2o_msg_post_wait(dev->iop, m, 60); }; /** @@ -59,9 +59,8 @@ static int i2o_bus_scan(struct i2o_device *dev) * * Returns count. */ -static ssize_t i2o_bus_store_scan(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf, + size_t count) { struct i2o_device *i2o_dev = to_i2o_device(d); int rc; diff --git a/trunk/drivers/message/i2o/config-osm.c b/trunk/drivers/message/i2o/config-osm.c index 3bba7aa82e58..10432f665201 100644 --- a/trunk/drivers/message/i2o/config-osm.c +++ b/trunk/drivers/message/i2o/config-osm.c @@ -22,7 +22,7 @@ #include #define OSM_NAME "config-osm" -#define OSM_VERSION "1.323" +#define OSM_VERSION "1.248" #define OSM_DESCRIPTION "I2O Configuration OSM" /* access mode user rw */ diff --git a/trunk/drivers/message/i2o/core.h b/trunk/drivers/message/i2o/core.h index 90628562851e..9eefedb16211 100644 --- a/trunk/drivers/message/i2o/core.h +++ b/trunk/drivers/message/i2o/core.h @@ -14,6 +14,8 @@ */ /* Exec-OSM */ +extern struct bus_type i2o_bus_type; + extern struct i2o_driver i2o_exec_driver; extern int i2o_exec_lct_get(struct i2o_controller *); @@ -21,8 +23,6 @@ extern int __init i2o_exec_init(void); extern void __exit i2o_exec_exit(void); /* driver */ -extern struct bus_type i2o_bus_type; - extern int i2o_driver_dispatch(struct i2o_controller *, u32); extern int __init i2o_driver_init(void); @@ -33,27 +33,19 @@ extern int __init i2o_pci_init(void); extern void __exit i2o_pci_exit(void); /* device */ -extern struct device_attribute i2o_device_attrs[]; - extern void i2o_device_remove(struct i2o_device *); extern int i2o_device_parse_lct(struct i2o_controller *); /* IOP */ extern struct i2o_controller *i2o_iop_alloc(void); - -/** - * i2o_iop_free - Free the i2o_controller struct - * @c: I2O controller to free - */ -static inline void i2o_iop_free(struct i2o_controller *c) -{ - i2o_pool_free(&c->in_msg); - kfree(c); -} +extern void i2o_iop_free(struct i2o_controller *); extern int i2o_iop_add(struct i2o_controller *); extern void i2o_iop_remove(struct i2o_controller *); +/* config */ +extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); + /* control registers relative to c->base */ #define I2O_IRQ_STATUS 0x30 #define I2O_IRQ_MASK 0x34 diff --git a/trunk/drivers/message/i2o/device.c b/trunk/drivers/message/i2o/device.c index ee183053fa23..8eb50cdb8ae1 100644 --- a/trunk/drivers/message/i2o/device.c +++ b/trunk/drivers/message/i2o/device.c @@ -35,18 +35,18 @@ static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd, u32 type) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid); - msg->body[0] = cpu_to_le32(type); + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid, &msg->u.head[1]); + writel(type, &msg->body[0]); - return i2o_msg_post_wait(dev->iop, msg, 60); + return i2o_msg_post_wait(dev->iop, m, 60); } /** @@ -123,6 +123,7 @@ int i2o_device_claim_release(struct i2o_device *dev) return rc; } + /** * i2o_device_release - release the memory for a I2O device * @dev: I2O device which should be released @@ -139,10 +140,10 @@ static void i2o_device_release(struct device *dev) kfree(i2o_dev); } + /** - * i2o_device_show_class_id - Displays class id of I2O device - * @dev: device of which the class id should be displayed - * @attr: pointer to device attribute + * i2o_device_class_show_class_id - Displays class id of I2O device + * @cd: class device of which the class id should be displayed * @buf: buffer into which the class id should be printed * * Returns the number of bytes which are printed into the buffer. @@ -158,15 +159,15 @@ static ssize_t i2o_device_show_class_id(struct device *dev, } /** - * i2o_device_show_tid - Displays TID of I2O device - * @dev: device of which the TID should be displayed - * @attr: pointer to device attribute - * @buf: buffer into which the TID should be printed + * i2o_device_class_show_tid - Displays TID of I2O device + * @cd: class device of which the TID should be displayed + * @buf: buffer into which the class id should be printed * * Returns the number of bytes which are printed into the buffer. */ static ssize_t i2o_device_show_tid(struct device *dev, - struct device_attribute *attr, char *buf) + struct device_attribute *attr, + char *buf) { struct i2o_device *i2o_dev = to_i2o_device(dev); @@ -174,7 +175,6 @@ static ssize_t i2o_device_show_tid(struct device *dev, return strlen(buf) + 1; } -/* I2O device attributes */ struct device_attribute i2o_device_attrs[] = { __ATTR(class_id, S_IRUGO, i2o_device_show_class_id, NULL), __ATTR(tid, S_IRUGO, i2o_device_show_tid, NULL), @@ -193,10 +193,12 @@ static struct i2o_device *i2o_device_alloc(void) { struct i2o_device *dev; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); + dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return ERR_PTR(-ENOMEM); + memset(dev, 0, sizeof(*dev)); + INIT_LIST_HEAD(&dev->list); init_MUTEX(&dev->lock); @@ -206,6 +208,66 @@ static struct i2o_device *i2o_device_alloc(void) return dev; } +/** + * i2o_setup_sysfs_links - Adds attributes to the I2O device + * @cd: I2O class device which is added to the I2O device class + * + * This function get called when a I2O device is added to the class. It + * creates the attributes for each device and creates user/parent symlink + * if necessary. + * + * Returns 0 on success or negative error code on failure. + */ +static void i2o_setup_sysfs_links(struct i2o_device *i2o_dev) +{ + struct i2o_controller *c = i2o_dev->iop; + struct i2o_device *tmp; + + /* create user entries for this device */ + tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); + if (tmp && tmp != i2o_dev) + sysfs_create_link(&i2o_dev->device.kobj, + &tmp->device.kobj, "user"); + + /* create user entries refering to this device */ + list_for_each_entry(tmp, &c->devices, list) + if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid && + tmp != i2o_dev) + sysfs_create_link(&tmp->device.kobj, + &i2o_dev->device.kobj, "user"); + + /* create parent entries for this device */ + tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); + if (tmp && tmp != i2o_dev) + sysfs_create_link(&i2o_dev->device.kobj, + &tmp->device.kobj, "parent"); + + /* create parent entries refering to this device */ + list_for_each_entry(tmp, &c->devices, list) + if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid && + tmp != i2o_dev) + sysfs_create_link(&tmp->device.kobj, + &i2o_dev->device.kobj, "parent"); +} + +static void i2o_remove_sysfs_links(struct i2o_device *i2o_dev) +{ + struct i2o_controller *c = i2o_dev->iop; + struct i2o_device *tmp; + + sysfs_remove_link(&i2o_dev->device.kobj, "parent"); + sysfs_remove_link(&i2o_dev->device.kobj, "user"); + + list_for_each_entry(tmp, &c->devices, list) { + if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "parent"); + if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) + sysfs_remove_link(&tmp->device.kobj, "user"); + } +} + + + /** * i2o_device_add - allocate a new I2O device and add it to the IOP * @iop: I2O controller where the device is on @@ -220,57 +282,33 @@ static struct i2o_device *i2o_device_alloc(void) static struct i2o_device *i2o_device_add(struct i2o_controller *c, i2o_lct_entry * entry) { - struct i2o_device *i2o_dev, *tmp; + struct i2o_device *dev; - i2o_dev = i2o_device_alloc(); - if (IS_ERR(i2o_dev)) { + dev = i2o_device_alloc(); + if (IS_ERR(dev)) { printk(KERN_ERR "i2o: unable to allocate i2o device\n"); - return i2o_dev; + return dev; } - i2o_dev->lct_data = *entry; + dev->lct_data = *entry; + dev->iop = c; - snprintf(i2o_dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, - i2o_dev->lct_data.tid); + snprintf(dev->device.bus_id, BUS_ID_SIZE, "%d:%03x", c->unit, + dev->lct_data.tid); - i2o_dev->iop = c; - i2o_dev->device.parent = &c->device; + dev->device.parent = &c->device; - device_register(&i2o_dev->device); + device_register(&dev->device); - list_add_tail(&i2o_dev->list, &c->devices); + list_add_tail(&dev->list, &c->devices); - /* create user entries for this device */ - tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); - if (tmp && (tmp != i2o_dev)) - sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, - "user"); - - /* create user entries refering to this device */ - list_for_each_entry(tmp, &c->devices, list) - if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) - && (tmp != i2o_dev)) - sysfs_create_link(&tmp->device.kobj, - &i2o_dev->device.kobj, "user"); + i2o_setup_sysfs_links(dev); - /* create parent entries for this device */ - tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); - if (tmp && (tmp != i2o_dev)) - sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, - "parent"); + i2o_driver_notify_device_add_all(dev); - /* create parent entries refering to this device */ - list_for_each_entry(tmp, &c->devices, list) - if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) - && (tmp != i2o_dev)) - sysfs_create_link(&tmp->device.kobj, - &i2o_dev->device.kobj, "parent"); + pr_debug("i2o: device %s added\n", dev->device.bus_id); - i2o_driver_notify_device_add_all(i2o_dev); - - pr_debug("i2o: device %s added\n", i2o_dev->device.bus_id); - - return i2o_dev; + return dev; } /** @@ -283,22 +321,9 @@ static struct i2o_device *i2o_device_add(struct i2o_controller *c, */ void i2o_device_remove(struct i2o_device *i2o_dev) { - struct i2o_device *tmp; - struct i2o_controller *c = i2o_dev->iop; - i2o_driver_notify_device_remove_all(i2o_dev); - - sysfs_remove_link(&i2o_dev->device.kobj, "parent"); - sysfs_remove_link(&i2o_dev->device.kobj, "user"); - - list_for_each_entry(tmp, &c->devices, list) { - if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) - sysfs_remove_link(&tmp->device.kobj, "parent"); - if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) - sysfs_remove_link(&tmp->device.kobj, "user"); - } + i2o_remove_sysfs_links(i2o_dev); list_del(&i2o_dev->list); - device_unregister(&i2o_dev->device); } @@ -316,83 +341,56 @@ int i2o_device_parse_lct(struct i2o_controller *c) { struct i2o_device *dev, *tmp; i2o_lct *lct; - u32 *dlct = c->dlct.virt; - int max = 0, i = 0; - u16 table_size; - u32 buf; + int i; + int max; down(&c->lct_lock); kfree(c->lct); - buf = le32_to_cpu(*dlct++); - table_size = buf & 0xffff; + lct = c->dlct.virt; - lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); - if (!lct) { + c->lct = kmalloc(lct->table_size * 4, GFP_KERNEL); + if (!c->lct) { up(&c->lct_lock); return -ENOMEM; } - lct->lct_ver = buf >> 28; - lct->boot_tid = buf >> 16 & 0xfff; - lct->table_size = table_size; - lct->change_ind = le32_to_cpu(*dlct++); - lct->iop_flags = le32_to_cpu(*dlct++); + if (lct->table_size * 4 > c->dlct.len) { + memcpy(c->lct, c->dlct.virt, c->dlct.len); + up(&c->lct_lock); + return -EAGAIN; + } - table_size -= 3; + memcpy(c->lct, c->dlct.virt, lct->table_size * 4); + + lct = c->lct; + + max = (lct->table_size - 3) / 9; pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max, lct->table_size); - while (table_size > 0) { - i2o_lct_entry *entry = &lct->lct_entry[max]; + /* remove devices, which are not in the LCT anymore */ + list_for_each_entry_safe(dev, tmp, &c->devices, list) { int found = 0; - buf = le32_to_cpu(*dlct++); - entry->entry_size = buf & 0xffff; - entry->tid = buf >> 16 & 0xfff; - - entry->change_ind = le32_to_cpu(*dlct++); - entry->device_flags = le32_to_cpu(*dlct++); - - buf = le32_to_cpu(*dlct++); - entry->class_id = buf & 0xfff; - entry->version = buf >> 12 & 0xf; - entry->vendor_id = buf >> 16; - - entry->sub_class = le32_to_cpu(*dlct++); - - buf = le32_to_cpu(*dlct++); - entry->user_tid = buf & 0xfff; - entry->parent_tid = buf >> 12 & 0xfff; - entry->bios_info = buf >> 24; - - memcpy(&entry->identity_tag, dlct, 8); - dlct += 2; - - entry->event_capabilities = le32_to_cpu(*dlct++); - - /* add new devices, which are new in the LCT */ - list_for_each_entry_safe(dev, tmp, &c->devices, list) { - if (entry->tid == dev->lct_data.tid) { + for (i = 0; i < max; i++) { + if (lct->lct_entry[i].tid == dev->lct_data.tid) { found = 1; break; } } if (!found) - i2o_device_add(c, entry); - - table_size -= 9; - max++; + i2o_device_remove(dev); } - /* remove devices, which are not in the LCT anymore */ - list_for_each_entry_safe(dev, tmp, &c->devices, list) { + /* add new devices, which are new in the LCT */ + for (i = 0; i < max; i++) { int found = 0; - for (i = 0; i < max; i++) { + list_for_each_entry_safe(dev, tmp, &c->devices, list) { if (lct->lct_entry[i].tid == dev->lct_data.tid) { found = 1; break; @@ -400,14 +398,14 @@ int i2o_device_parse_lct(struct i2o_controller *c) } if (!found) - i2o_device_remove(dev); + i2o_device_add(c, &lct->lct_entry[i]); } - up(&c->lct_lock); return 0; } + /* * Run time support routines */ @@ -421,9 +419,13 @@ int i2o_device_parse_lct(struct i2o_controller *c) * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. */ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, - int oplen, void *reslist, int reslen) + int oplen, void *reslist, int reslen) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; + u32 *res32 = (u32 *) reslist; + u32 *restmp = (u32 *) reslist; + int len = 0; int i = 0; int rc; struct i2o_dma res; @@ -435,27 +437,26 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, if (i2o_dma_alloc(dev, &res, reslen, GFP_KERNEL)) return -ENOMEM; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) { + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) { i2o_dma_free(dev, &res); - return PTR_ERR(msg); + return -ETIMEDOUT; } i = 0; - msg->u.head[1] = - cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid); - msg->body[i++] = cpu_to_le32(0x00000000); - msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */ - memcpy(&msg->body[i], oplist, oplen); + writel(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid, + &msg->u.head[1]); + writel(0, &msg->body[i++]); + writel(0x4C000000 | oplen, &msg->body[i++]); /* OperationList */ + memcpy_toio(&msg->body[i], oplist, oplen); i += (oplen / 4 + (oplen % 4 ? 1 : 0)); - msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */ - msg->body[i++] = cpu_to_le32(res.phys); + writel(0xD0000000 | res.len, &msg->body[i++]); /* ResultList */ + writel(res.phys, &msg->body[i++]); - msg->u.head[0] = - cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | - SGL_OFFSET_5); + writel(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) | + SGL_OFFSET_5, &msg->u.head[0]); - rc = i2o_msg_post_wait_mem(c, msg, 10, &res); + rc = i2o_msg_post_wait_mem(c, m, 10, &res); /* This only looks like a memory leak - don't "fix" it. */ if (rc == -ETIMEDOUT) @@ -464,7 +465,36 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, memcpy(reslist, res.virt, res.len); i2o_dma_free(dev, &res); - return rc; + /* Query failed */ + if (rc) + return rc; + /* + * Calculate number of bytes of Result LIST + * We need to loop through each Result BLOCK and grab the length + */ + restmp = res32 + 1; + len = 1; + for (i = 0; i < (res32[0] & 0X0000FFFF); i++) { + if (restmp[0] & 0x00FF0000) { /* BlockStatus != SUCCESS */ + printk(KERN_WARNING + "%s - Error:\n ErrorInfoSize = 0x%02x, " + "BlockStatus = 0x%02x, BlockSize = 0x%04x\n", + (cmd == + I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" : + "PARAMS_GET", res32[1] >> 24, + (res32[1] >> 16) & 0xFF, res32[1] & 0xFFFF); + + /* + * If this is the only request,than we return an error + */ + if ((res32[0] & 0x0000FFFF) == 1) { + return -((res32[1] >> 16) & 0xFF); /* -BlockStatus */ + } + } + len += restmp[0] & 0x0000FFFF; /* Length of res BLOCK */ + restmp += restmp[0] & 0x0000FFFF; /* Skip to next BLOCK */ + } + return (len << 2); /* bytes used by result list */ } /* @@ -473,25 +503,28 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist, int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, void *buf, int buflen) { - u32 opblk[] = { cpu_to_le32(0x00000001), - cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET), - cpu_to_le32((s16) field << 16 | 0x00000001) - }; + u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; u8 *resblk; /* 8 bytes for header */ - int rc; + int size; + + if (field == -1) /* whole group */ + opblk[4] = -1; resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC); if (!resblk) return -ENOMEM; - rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, - sizeof(opblk), resblk, buflen + 8); + size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk, + sizeof(opblk), resblk, buflen + 8); memcpy(buf, resblk + 8, buflen); /* cut off header */ kfree(resblk); - return rc; + if (size > buflen) + return buflen; + + return size; } /* @@ -501,12 +534,12 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field, * else return specific fields * ibuf contains fieldindexes * - * if oper == I2O_PARAMS_LIST_GET, get from specific rows - * if fieldcount == -1 return all fields + * if oper == I2O_PARAMS_LIST_GET, get from specific rows + * if fieldcount == -1 return all fields * ibuf contains rowcount, keyvalues - * else return specific fields + * else return specific fields * fieldcount is # of fieldindexes - * ibuf contains fieldindexes, rowcount, keyvalues + * ibuf contains fieldindexes, rowcount, keyvalues * * You could also use directly function i2o_issue_params(). */ diff --git a/trunk/drivers/message/i2o/driver.c b/trunk/drivers/message/i2o/driver.c index 64130227574f..0fb9c4e2ad4c 100644 --- a/trunk/drivers/message/i2o/driver.c +++ b/trunk/drivers/message/i2o/driver.c @@ -61,10 +61,12 @@ static int i2o_bus_match(struct device *dev, struct device_driver *drv) }; /* I2O bus type */ +extern struct device_attribute i2o_device_attrs[]; + struct bus_type i2o_bus_type = { .name = "i2o", .match = i2o_bus_match, - .dev_attrs = i2o_device_attrs + .dev_attrs = i2o_device_attrs, }; /** @@ -217,14 +219,14 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m) /* cut of header from message size (in 32-bit words) */ size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5; - evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); + evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO); if (!evt) return -ENOMEM; evt->size = size; evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt); evt->event_indicator = le32_to_cpu(msg->body[0]); - memcpy(&evt->data, &msg->body[1], size * 4); + memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4); list_for_each_entry_safe(dev, tmp, &c->devices, list) if (dev->lct_data.tid == tid) { @@ -347,10 +349,12 @@ int __init i2o_driver_init(void) osm_info("max drivers = %d\n", i2o_max_drivers); i2o_drivers = - kzalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL); + kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL); if (!i2o_drivers) return -ENOMEM; + memset(i2o_drivers, 0, i2o_max_drivers * sizeof(*i2o_drivers)); + rc = bus_register(&i2o_bus_type); if (rc < 0) diff --git a/trunk/drivers/message/i2o/exec-osm.c b/trunk/drivers/message/i2o/exec-osm.c index 9bb9859f6dfe..9c339a2505b0 100644 --- a/trunk/drivers/message/i2o/exec-osm.c +++ b/trunk/drivers/message/i2o/exec-osm.c @@ -33,7 +33,7 @@ #include #include #include -#include /* wait_event_interruptible_timeout() needs this */ +#include /* wait_event_interruptible_timeout() needs this */ #include /* HZ */ #include "core.h" @@ -75,9 +75,11 @@ static struct i2o_exec_wait *i2o_exec_wait_alloc(void) { struct i2o_exec_wait *wait; - wait = kzalloc(sizeof(*wait), GFP_KERNEL); + wait = kmalloc(sizeof(*wait), GFP_KERNEL); if (!wait) - return NULL; + return ERR_PTR(-ENOMEM); + + memset(wait, 0, sizeof(*wait)); INIT_LIST_HEAD(&wait->list); @@ -112,12 +114,13 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) * Returns 0 on success, negative error code on timeout or positive error * code from reply. */ -int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, - unsigned long timeout, struct i2o_dma *dma) +int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long + timeout, struct i2o_dma *dma) { DECLARE_WAIT_QUEUE_HEAD(wq); struct i2o_exec_wait *wait; static u32 tcntxt = 0x80000000; + struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m); int rc = 0; wait = i2o_exec_wait_alloc(); @@ -135,15 +138,15 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, * We will only use transaction contexts >= 0x80000000 for POST WAIT, * so we could find a POST WAIT reply easier in the reply handler. */ - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); + writel(i2o_exec_driver.context, &msg->u.s.icntxt); wait->tcntxt = tcntxt++; - msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt); + writel(wait->tcntxt, &msg->u.s.tcntxt); /* * Post the message to the controller. At some point later it will * return. If we time out before it returns then complete will be zero. */ - i2o_msg_post(c, msg); + i2o_msg_post(c, m); if (!wait->complete) { wait->wq = &wq; @@ -263,14 +266,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, * * Returns number of bytes printed into buffer. */ -static ssize_t i2o_exec_show_vendor_id(struct device *d, - struct device_attribute *attr, char *buf) +static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf) { struct i2o_device *dev = to_i2o_device(d); u16 id; - if (!i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { - sprintf(buf, "0x%04x", le16_to_cpu(id)); + if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) { + sprintf(buf, "0x%04x", id); return strlen(buf) + 1; } @@ -284,15 +286,13 @@ static ssize_t i2o_exec_show_vendor_id(struct device *d, * * Returns number of bytes printed into buffer. */ -static ssize_t i2o_exec_show_product_id(struct device *d, - struct device_attribute *attr, - char *buf) +static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf) { struct i2o_device *dev = to_i2o_device(d); u16 id; - if (!i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { - sprintf(buf, "0x%04x", le16_to_cpu(id)); + if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) { + sprintf(buf, "0x%04x", id); return strlen(buf) + 1; } @@ -362,9 +362,7 @@ static void i2o_exec_lct_modified(struct i2o_controller *c) if (i2o_device_parse_lct(c) != -EAGAIN) change_ind = c->lct->change_ind + 1; -#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES i2o_exec_lct_notify(c, change_ind); -#endif }; /** @@ -387,22 +385,23 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, u32 context; if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { - struct i2o_message __iomem *pmsg; - u32 pm; - /* * If Fail bit is set we must take the transaction context of * the preserved message to find the right request again. */ + struct i2o_message __iomem *pmsg; + u32 pm; pm = le32_to_cpu(msg->body[3]); + pmsg = i2o_msg_in_to_virt(c, pm); - context = readl(&pmsg->u.s.tcntxt); i2o_report_status(KERN_INFO, "i2o_core", msg); + context = readl(&pmsg->u.s.tcntxt); + /* Release the preserved msg */ - i2o_msg_nop_mfa(c, pm); + i2o_msg_nop(c, pm); } else context = le32_to_cpu(msg->u.s.tcntxt); @@ -463,26 +462,25 @@ static void i2o_exec_event(struct i2o_event *evt) */ int i2o_exec_lct_get(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; int i = 0; int rc = -EAGAIN; for (i = 1; i <= I2O_LCT_GET_TRIES; i++) { - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = - cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->body[0] = cpu_to_le32(0xffffffff); - msg->body[1] = cpu_to_le32(0x00000000); - msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); - msg->body[3] = cpu_to_le32(c->dlct.phys); - - rc = i2o_msg_post_wait(c, msg, I2O_TIMEOUT_LCT_GET); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]); + writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(0xffffffff, &msg->body[0]); + writel(0x00000000, &msg->body[1]); + writel(0xd0000000 | c->dlct.len, &msg->body[2]); + writel(c->dlct.phys, &msg->body[3]); + + rc = i2o_msg_post_wait(c, m, I2O_TIMEOUT_LCT_GET); if (rc < 0) break; @@ -508,29 +506,29 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) { i2o_status_block *sb = c->status_block.virt; struct device *dev; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; dev = &c->pdev->dev; - if (i2o_dma_realloc - (dev, &c->dlct, le32_to_cpu(sb->expected_lct_size), GFP_KERNEL)) + if (i2o_dma_realloc(dev, &c->dlct, sb->expected_lct_size, GFP_KERNEL)) return -ENOMEM; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); - msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); - msg->u.s.tcntxt = cpu_to_le32(0x00000000); - msg->body[0] = cpu_to_le32(0xffffffff); - msg->body[1] = cpu_to_le32(change_ind); - msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len); - msg->body[3] = cpu_to_le32(c->dlct.phys); - - i2o_msg_post(c, msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]); + writel(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_exec_driver.context, &msg->u.s.icntxt); + writel(0, &msg->u.s.tcntxt); /* FIXME */ + writel(0xffffffff, &msg->body[0]); + writel(change_ind, &msg->body[1]); + writel(0xd0000000 | c->dlct.len, &msg->body[2]); + writel(c->dlct.phys, &msg->body[3]); + + i2o_msg_post(c, m); return 0; }; diff --git a/trunk/drivers/message/i2o/i2o_block.c b/trunk/drivers/message/i2o/i2o_block.c index 5b1febed3133..f283b5bafdd3 100644 --- a/trunk/drivers/message/i2o/i2o_block.c +++ b/trunk/drivers/message/i2o/i2o_block.c @@ -59,12 +59,10 @@ #include #include -#include - #include "i2o_block.h" #define OSM_NAME "block-osm" -#define OSM_VERSION "1.325" +#define OSM_VERSION "1.287" #define OSM_DESCRIPTION "I2O Block Device OSM" static struct i2o_driver i2o_block_driver; @@ -132,20 +130,20 @@ static int i2o_block_remove(struct device *dev) */ static int i2o_block_device_flush(struct i2o_device *dev) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(60 << 16); + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); + writel(60 << 16, &msg->body[0]); osm_debug("Flushing...\n"); - return i2o_msg_post_wait(dev->iop, msg, 60); + return i2o_msg_post_wait(dev->iop, m, 60); }; /** @@ -183,21 +181,21 @@ static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk, */ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) { - struct i2o_message *msg; - - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(-1); - msg->body[1] = cpu_to_le32(0x00000000); + struct i2o_message __iomem *msg; + u32 m; + + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); + writel(-1, &msg->body[0]); + writel(0, &msg->body[1]); osm_debug("Mounting...\n"); - return i2o_msg_post_wait(dev->iop, msg, 2); + return i2o_msg_post_wait(dev->iop, m, 2); }; /** @@ -212,20 +210,20 @@ static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id) */ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg) == I2O_QUEUE_EMPTY) - return PTR_ERR(msg); + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(-1); + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); + writel(-1, &msg->body[0]); osm_debug("Locking...\n"); - return i2o_msg_post_wait(dev->iop, msg, 2); + return i2o_msg_post_wait(dev->iop, m, 2); }; /** @@ -240,20 +238,20 @@ static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id) */ static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; - msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(media_id); + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid, + &msg->u.head[1]); + writel(media_id, &msg->body[0]); osm_debug("Unlocking...\n"); - return i2o_msg_post_wait(dev->iop, msg, 2); + return i2o_msg_post_wait(dev->iop, m, 2); }; /** @@ -269,21 +267,21 @@ static int i2o_block_device_power(struct i2o_block_device *dev, u8 op) { struct i2o_device *i2o_dev = dev->i2o_dev; struct i2o_controller *c = i2o_dev->iop; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; int rc; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev-> - lct_data.tid); - msg->body[0] = cpu_to_le32(op << 24); + writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data. + tid, &msg->u.head[1]); + writel(op << 24, &msg->body[0]); osm_debug("Power...\n"); - rc = i2o_msg_post_wait(c, msg, 60); + rc = i2o_msg_post_wait(c, m, 60); if (!rc) dev->power = op; @@ -333,7 +331,7 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq) */ static inline int i2o_block_sglist_alloc(struct i2o_controller *c, struct i2o_block_request *ireq, - u32 ** mptr) + u32 __iomem ** mptr) { int nents; enum dma_data_direction direction; @@ -468,7 +466,7 @@ static void i2o_block_end_request(struct request *req, int uptodate, spin_lock_irqsave(q->queue_lock, flags); - end_that_request_last(req, uptodate); + end_that_request_last(req); if (likely(dev)) { dev->open_queue_depth--; @@ -747,9 +745,10 @@ static int i2o_block_transfer(struct request *req) struct i2o_block_device *dev = req->rq_disk->private_data; struct i2o_controller *c; int tid = dev->i2o_dev->lct_data.tid; - struct i2o_message *msg; - u32 *mptr; + struct i2o_message __iomem *msg; + u32 __iomem *mptr; struct i2o_block_request *ireq = req->special; + u32 m; u32 tcntxt; u32 sgl_offset = SGL_OFFSET_8; u32 ctl_flags = 0x00000000; @@ -764,9 +763,9 @@ static int i2o_block_transfer(struct request *req) c = dev->i2o_dev->iop; - msg = i2o_msg_get(c); - if (IS_ERR(msg)) { - rc = PTR_ERR(msg); + m = i2o_msg_get(c, &msg); + if (m == I2O_QUEUE_EMPTY) { + rc = -EBUSY; goto exit; } @@ -776,8 +775,8 @@ static int i2o_block_transfer(struct request *req) goto nop_msg; } - msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context); - msg->u.s.tcntxt = cpu_to_le32(tcntxt); + writel(i2o_block_driver.context, &msg->u.s.icntxt); + writel(tcntxt, &msg->u.s.tcntxt); mptr = &msg->body[0]; @@ -835,11 +834,11 @@ static int i2o_block_transfer(struct request *req) sgl_offset = SGL_OFFSET_12; - msg->u.head[1] = - cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid); + writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid, + &msg->u.head[1]); - *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); - *mptr++ = cpu_to_le32(tid); + writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++); + writel(tid, mptr++); /* * ENABLE_DISCONNECT @@ -847,31 +846,29 @@ static int i2o_block_transfer(struct request *req) * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME */ if (rq_data_dir(req) == READ) { - cmd[0] = READ_10; + cmd[0] = 0x28; scsi_flags = 0x60a0000a; } else { - cmd[0] = WRITE_10; + cmd[0] = 0x2A; scsi_flags = 0xa0a0000a; } - *mptr++ = cpu_to_le32(scsi_flags); + writel(scsi_flags, mptr++); *((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec); *((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec); - memcpy(mptr, cmd, 10); + memcpy_toio(mptr, cmd, 10); mptr += 4; - *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT); + writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++); } else #endif { - msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); - *mptr++ = cpu_to_le32(ctl_flags); - *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT); - *mptr++ = - cpu_to_le32((u32) (req->sector << KERNEL_SECTOR_SHIFT)); - *mptr++ = - cpu_to_le32(req->sector >> (32 - KERNEL_SECTOR_SHIFT)); + writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]); + writel(ctl_flags, mptr++); + writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++); + writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++); + writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++); } if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { @@ -879,13 +876,13 @@ static int i2o_block_transfer(struct request *req) goto context_remove; } - msg->u.head[0] = - cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); + writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | + sgl_offset, &msg->u.head[0]); list_add_tail(&ireq->queue, &dev->open_queue); dev->open_queue_depth++; - i2o_msg_post(c, msg); + i2o_msg_post(c, m); return 0; @@ -893,7 +890,7 @@ static int i2o_block_transfer(struct request *req) i2o_cntxt_list_remove(c, req); nop_msg: - i2o_msg_nop(c, msg); + i2o_msg_nop(c, m); exit: return rc; @@ -981,12 +978,13 @@ static struct i2o_block_device *i2o_block_device_alloc(void) struct request_queue *queue; int rc; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); + dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (!dev) { osm_err("Insufficient memory to allocate I2O Block disk.\n"); rc = -ENOMEM; goto exit; } + memset(dev, 0, sizeof(*dev)); INIT_LIST_HEAD(&dev->open_queue); spin_lock_init(&dev->lock); @@ -1051,8 +1049,8 @@ static int i2o_block_probe(struct device *dev) int rc; u64 size; u32 blocksize; + u32 flags, status; u16 body_size = 4; - u16 power; unsigned short max_sectors; #ifdef CONFIG_I2O_EXT_ADAPTEC @@ -1110,20 +1108,22 @@ static int i2o_block_probe(struct device *dev) * Ask for the current media data. If that isn't supported * then we ask for the device capacity data */ - if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || - !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { - blk_queue_hardsect_size(queue, le32_to_cpu(blocksize)); + if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || + i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { + blk_queue_hardsect_size(queue, blocksize); } else osm_warn("unable to get blocksize of %s\n", gd->disk_name); - if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || - !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { - set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT); + if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) || + i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) { + set_capacity(gd, size >> KERNEL_SECTOR_SHIFT); } else osm_warn("could not get size of %s\n", gd->disk_name); - if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2)) - i2o_blk_dev->power = power; + if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2)) + i2o_blk_dev->power = 0; + i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4); + i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4); i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff); diff --git a/trunk/drivers/message/i2o/i2o_config.c b/trunk/drivers/message/i2o/i2o_config.c index 89daf67b764d..3c3a7abebb1b 100644 --- a/trunk/drivers/message/i2o/i2o_config.c +++ b/trunk/drivers/message/i2o/i2o_config.c @@ -36,12 +36,12 @@ #include -#define SG_TABLESIZE 30 +#include "core.h" -extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int); +#define SG_TABLESIZE 30 -static int i2o_cfg_ioctl(struct inode *, struct file *, unsigned int, - unsigned long); +static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, + unsigned long arg); static spinlock_t i2o_config_lock; @@ -230,7 +230,8 @@ static int i2o_cfg_swdl(unsigned long arg) struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; unsigned char maxfrag = 0, curfrag = 1; struct i2o_dma buffer; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; unsigned int status = 0, swlen = 0, fragsize = 8192; struct i2o_controller *c; @@ -256,34 +257,31 @@ static int i2o_cfg_swdl(unsigned long arg) if (!c) return -ENXIO; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) { - i2o_msg_nop(c, msg); + i2o_msg_nop(c, m); return -ENOMEM; } __copy_from_user(buffer.virt, kxfer.buf, fragsize); - msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(0); - msg->body[0] = - cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer. - sw_type) << 16) | - (((u32) maxfrag) << 8) | (((u32) curfrag))); - msg->body[1] = cpu_to_le32(swlen); - msg->body[2] = cpu_to_le32(kxfer.sw_id); - msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); - msg->body[4] = cpu_to_le32(buffer.phys); + writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); + writel(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + writel((((u32) kxfer.flags) << 24) | (((u32) kxfer.sw_type) << 16) | + (((u32) maxfrag) << 8) | (((u32) curfrag)), &msg->body[0]); + writel(swlen, &msg->body[1]); + writel(kxfer.sw_id, &msg->body[2]); + writel(0xD0000000 | fragsize, &msg->body[3]); + writel(buffer.phys, &msg->body[4]); osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); - status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); + status = i2o_msg_post_wait_mem(c, m, 60, &buffer); if (status != -ETIMEDOUT) i2o_dma_free(&c->pdev->dev, &buffer); @@ -304,7 +302,8 @@ static int i2o_cfg_swul(unsigned long arg) struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; unsigned char maxfrag = 0, curfrag = 1; struct i2o_dma buffer; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; unsigned int status = 0, swlen = 0, fragsize = 8192; struct i2o_controller *c; int ret = 0; @@ -331,30 +330,30 @@ static int i2o_cfg_swul(unsigned long arg) if (!c) return -ENXIO; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize, GFP_KERNEL)) { - i2o_msg_nop(c, msg); + i2o_msg_nop(c, m); return -ENOMEM; } - msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(0); - msg->body[0] = - cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer. - sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag); - msg->body[1] = cpu_to_le32(swlen); - msg->body[2] = cpu_to_le32(kxfer.sw_id); - msg->body[3] = cpu_to_le32(0xD0000000 | fragsize); - msg->body[4] = cpu_to_le32(buffer.phys); + writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]); + writel(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + writel((u32) kxfer.flags << 24 | (u32) kxfer. + sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag, + &msg->body[0]); + writel(swlen, &msg->body[1]); + writel(kxfer.sw_id, &msg->body[2]); + writel(0xD0000000 | fragsize, &msg->body[3]); + writel(buffer.phys, &msg->body[4]); osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); - status = i2o_msg_post_wait_mem(c, msg, 60, &buffer); + status = i2o_msg_post_wait_mem(c, m, 60, &buffer); if (status != I2O_POST_WAIT_OK) { if (status != -ETIMEDOUT) @@ -381,7 +380,8 @@ static int i2o_cfg_swdel(unsigned long arg) struct i2o_controller *c; struct i2o_sw_xfer kxfer; struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; unsigned int swlen; int token; @@ -395,21 +395,21 @@ static int i2o_cfg_swdel(unsigned long arg) if (!c) return -ENXIO; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; - msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(0); - msg->body[0] = - cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16); - msg->body[1] = cpu_to_le32(swlen); - msg->body[2] = cpu_to_le32(kxfer.sw_id); + writel(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + writel((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16, + &msg->body[0]); + writel(swlen, &msg->body[1]); + writel(kxfer.sw_id, &msg->body[2]); - token = i2o_msg_post_wait(c, msg, 10); + token = i2o_msg_post_wait(c, m, 10); if (token != I2O_POST_WAIT_OK) { osm_info("swdel failed, DetailedStatus = %d\n", token); @@ -423,24 +423,25 @@ static int i2o_cfg_validate(unsigned long arg) { int token; int iop = (int)arg; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; struct i2o_controller *c; c = i2o_find_iop(iop); if (!c) return -ENXIO; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(0); + writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(0, &msg->u.head[3]); - token = i2o_msg_post_wait(c, msg, 10); + token = i2o_msg_post_wait(c, m, 10); if (token != I2O_POST_WAIT_OK) { osm_info("Can't validate configuration, ErrorStatus = %d\n", @@ -453,7 +454,8 @@ static int i2o_cfg_validate(unsigned long arg) static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg; struct i2o_evt_id kdesc; struct i2o_controller *c; @@ -472,19 +474,18 @@ static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp) if (!d) return -ENODEV; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -EBUSY; - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | - kdesc.tid); - msg->u.head[2] = cpu_to_le32(i2o_config_driver.context); - msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data)); - msg->body[0] = cpu_to_le32(kdesc.evt_mask); + writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | kdesc.tid, + &msg->u.head[1]); + writel(i2o_config_driver.context, &msg->u.head[2]); + writel(i2o_cntxt_list_add(c, fp->private_data), &msg->u.head[3]); + writel(kdesc.evt_mask, &msg->body[0]); - i2o_msg_post(c, msg); + i2o_msg_post(c, m); return 0; } @@ -536,6 +537,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, u32 sg_index = 0; i2o_status_block *sb; struct i2o_message *msg; + u32 m; unsigned int iop; cmd = (struct i2o_cmd_passthru32 __user *)arg; @@ -551,7 +553,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, return -ENXIO; } - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); sb = c->status_block.virt; @@ -583,15 +585,19 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, reply_size >>= 16; reply_size <<= 2; - reply = kzalloc(reply_size, GFP_KERNEL); + reply = kmalloc(reply_size, GFP_KERNEL); if (!reply) { printk(KERN_WARNING "%s: Could not allocate reply buffer\n", c->name); return -ENOMEM; } + memset(reply, 0, reply_size); sg_offset = (msg->u.head[0] >> 4) & 0x0f; + writel(i2o_config_driver.context, &msg->u.s.icntxt); + writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt); + memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); if (sg_offset) { struct sg_simple_element *sg; @@ -625,7 +631,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, goto cleanup; } sg_size = sg[i].flag_count & 0xffffff; - p = &(sg_list[sg_index]); + p = &(sg_list[sg_index++]); /* Allocate memory for the transfer */ if (i2o_dma_alloc (&c->pdev->dev, p, sg_size, @@ -636,7 +642,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, rcode = -ENOMEM; goto sg_list_cleanup; } - sg_index++; /* Copy in the user's SG buffer if necessary */ if (sg[i]. flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) { @@ -657,11 +662,9 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, } } - rcode = i2o_msg_post_wait(c, msg, 60); - if (rcode) { - reply[4] = ((u32) rcode) << 24; + rcode = i2o_msg_post_wait(c, m, 60); + if (rcode) goto sg_list_cleanup; - } if (sg_offset) { u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE]; @@ -711,7 +714,6 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, } } - sg_list_cleanup: /* Copy back the reply to user space */ if (reply_size) { // we wrote our own values for context - now restore the user supplied ones @@ -729,6 +731,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, } } + sg_list_cleanup: for (i = 0; i < sg_index; i++) i2o_dma_free(&c->pdev->dev, &sg_list[i]); @@ -777,7 +780,8 @@ static int i2o_cfg_passthru(unsigned long arg) u32 i = 0; void *p = NULL; i2o_status_block *sb; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; unsigned int iop; if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg)) @@ -789,7 +793,7 @@ static int i2o_cfg_passthru(unsigned long arg) return -ENXIO; } - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); sb = c->status_block.virt; @@ -816,15 +820,19 @@ static int i2o_cfg_passthru(unsigned long arg) reply_size >>= 16; reply_size <<= 2; - reply = kzalloc(reply_size, GFP_KERNEL); + reply = kmalloc(reply_size, GFP_KERNEL); if (!reply) { printk(KERN_WARNING "%s: Could not allocate reply buffer\n", c->name); return -ENOMEM; } + memset(reply, 0, reply_size); sg_offset = (msg->u.head[0] >> 4) & 0x0f; + writel(i2o_config_driver.context, &msg->u.s.icntxt); + writel(i2o_cntxt_list_add(c, reply), &msg->u.s.tcntxt); + memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE); if (sg_offset) { struct sg_simple_element *sg; @@ -886,11 +894,9 @@ static int i2o_cfg_passthru(unsigned long arg) } } - rcode = i2o_msg_post_wait(c, msg, 60); - if (rcode) { - reply[4] = ((u32) rcode) << 24; + rcode = i2o_msg_post_wait(c, m, 60); + if (rcode) goto sg_list_cleanup; - } if (sg_offset) { u32 msg[128]; @@ -940,7 +946,6 @@ static int i2o_cfg_passthru(unsigned long arg) } } - sg_list_cleanup: /* Copy back the reply to user space */ if (reply_size) { // we wrote our own values for context - now restore the user supplied ones @@ -957,6 +962,7 @@ static int i2o_cfg_passthru(unsigned long arg) } } + sg_list_cleanup: for (i = 0; i < sg_index; i++) kfree(sg_list[i]); diff --git a/trunk/drivers/message/i2o/i2o_lan.h b/trunk/drivers/message/i2o/i2o_lan.h index 6502b817df58..561d63304d7e 100644 --- a/trunk/drivers/message/i2o/i2o_lan.h +++ b/trunk/drivers/message/i2o/i2o_lan.h @@ -103,14 +103,14 @@ #define I2O_LAN_DSC_SUSPENDED 0x11 struct i2o_packet_info { - u32 offset:24; - u32 flags:8; - u32 len:24; - u32 status:8; + u32 offset : 24; + u32 flags : 8; + u32 len : 24; + u32 status : 8; }; struct i2o_bucket_descriptor { - u32 context; /* FIXME: 64bit support */ + u32 context; /* FIXME: 64bit support */ struct i2o_packet_info packet_info[1]; }; @@ -127,14 +127,14 @@ struct i2o_lan_local { u8 unit; struct i2o_device *i2o_dev; - struct fddi_statistics stats; /* see also struct net_device_stats */ - unsigned short (*type_trans) (struct sk_buff *, struct net_device *); - atomic_t buckets_out; /* nbr of unused buckets on DDM */ - atomic_t tx_out; /* outstanding TXes */ - u8 tx_count; /* packets in one TX message frame */ - u16 tx_max_out; /* DDM's Tx queue len */ - u8 sgl_max; /* max SGLs in one message frame */ - u32 m; /* IOP address of the batch msg frame */ + struct fddi_statistics stats; /* see also struct net_device_stats */ + unsigned short (*type_trans)(struct sk_buff *, struct net_device *); + atomic_t buckets_out; /* nbr of unused buckets on DDM */ + atomic_t tx_out; /* outstanding TXes */ + u8 tx_count; /* packets in one TX message frame */ + u16 tx_max_out; /* DDM's Tx queue len */ + u8 sgl_max; /* max SGLs in one message frame */ + u32 m; /* IOP address of the batch msg frame */ struct work_struct i2o_batch_send_task; int send_active; @@ -144,16 +144,16 @@ struct i2o_lan_local { spinlock_t tx_lock; - u32 max_size_mc_table; /* max number of multicast addresses */ + u32 max_size_mc_table; /* max number of multicast addresses */ /* LAN OSM configurable parameters are here: */ - u16 max_buckets_out; /* max nbr of buckets to send to DDM */ - u16 bucket_thresh; /* send more when this many used */ + u16 max_buckets_out; /* max nbr of buckets to send to DDM */ + u16 bucket_thresh; /* send more when this many used */ u16 rx_copybreak; - u8 tx_batch_mode; /* Set when using batch mode sends */ - u32 i2o_event_mask; /* To turn on interesting event flags */ + u8 tx_batch_mode; /* Set when using batch mode sends */ + u32 i2o_event_mask; /* To turn on interesting event flags */ }; -#endif /* _I2O_LAN_H */ +#endif /* _I2O_LAN_H */ diff --git a/trunk/drivers/message/i2o/i2o_proc.c b/trunk/drivers/message/i2o/i2o_proc.c index 2a0c42b8cda5..d559a1758363 100644 --- a/trunk/drivers/message/i2o/i2o_proc.c +++ b/trunk/drivers/message/i2o/i2o_proc.c @@ -28,7 +28,7 @@ */ #define OSM_NAME "proc-osm" -#define OSM_VERSION "1.316" +#define OSM_VERSION "1.145" #define OSM_DESCRIPTION "I2O ProcFS OSM" #define I2O_MAX_MODULES 4 diff --git a/trunk/drivers/message/i2o/i2o_scsi.c b/trunk/drivers/message/i2o/i2o_scsi.c index f9e5a23697a1..9f1744c3933b 100644 --- a/trunk/drivers/message/i2o/i2o_scsi.c +++ b/trunk/drivers/message/i2o/i2o_scsi.c @@ -70,7 +70,7 @@ #include #define OSM_NAME "scsi-osm" -#define OSM_VERSION "1.316" +#define OSM_VERSION "1.282" #define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" static struct i2o_driver i2o_scsi_driver; @@ -113,7 +113,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) list_for_each_entry(i2o_dev, &c->devices, list) if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { - if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) && (type == 0x01)) /* SCSI bus */ max_channel++; } @@ -146,7 +146,7 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) i = 0; list_for_each_entry(i2o_dev, &c->devices, list) if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { - if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) + if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) && (type == 0x01)) /* only SCSI bus */ i2o_shost->channel[i++] = i2o_dev; @@ -238,15 +238,13 @@ static int i2o_scsi_probe(struct device *dev) u8 type; struct i2o_device *d = i2o_shost->channel[0]; - if (!i2o_parm_field_get(d, 0x0000, 0, &type, 1) + if (i2o_parm_field_get(d, 0x0000, 0, &type, 1) && (type == 0x01)) /* SCSI bus */ - if (!i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { + if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { channel = 0; if (i2o_dev->lct_data.class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE) - lun = - cpu_to_le64(i2o_shost-> - lun++); + lun = i2o_shost->lun++; else lun = 0; } @@ -255,10 +253,10 @@ static int i2o_scsi_probe(struct device *dev) break; case I2O_CLASS_SCSI_PERIPHERAL: - if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4)) + if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0) return -EFAULT; - if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8)) + if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0) return -EFAULT; parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); @@ -283,22 +281,20 @@ static int i2o_scsi_probe(struct device *dev) return -EFAULT; } - if (le32_to_cpu(id) >= scsi_host->max_id) { - osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", - le32_to_cpu(id), scsi_host->max_id); + if (id >= scsi_host->max_id) { + osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id, + scsi_host->max_id); return -EFAULT; } - if (le64_to_cpu(lun) >= scsi_host->max_lun) { - osm_warn("SCSI device lun (%lu) >= max_lun of I2O host (%d)", - (long unsigned int)le64_to_cpu(lun), - scsi_host->max_lun); + if (lun >= scsi_host->max_lun) { + osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)", + (unsigned int)lun, scsi_host->max_lun); return -EFAULT; } scsi_dev = - __scsi_add_device(i2o_shost->scsi_host, channel, le32_to_cpu(id), - le64_to_cpu(lun), i2o_dev); + __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); if (IS_ERR(scsi_dev)) { osm_warn("can not add SCSI device %03x\n", @@ -309,9 +305,8 @@ static int i2o_scsi_probe(struct device *dev) sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj, "scsi"); - osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %ld\n", - i2o_dev->lct_data.tid, channel, le32_to_cpu(id), - (long unsigned int)le64_to_cpu(lun)); + osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n", + i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); return 0; }; @@ -515,7 +510,8 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, struct i2o_controller *c; struct i2o_device *i2o_dev; int tid; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; /* * ENABLE_DISCONNECT * SIMPLE_TAG @@ -523,7 +519,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, */ u32 scsi_flags = 0x20a00000; u32 sgl_offset; - u32 *mptr; + u32 __iomem *mptr; u32 cmd = I2O_CMD_SCSI_EXEC << 24; int rc = 0; @@ -580,8 +576,8 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, * throw it back to the scsi layer */ - msg = i2o_msg_get(c); - if (IS_ERR(msg)) { + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) { rc = SCSI_MLQUEUE_HOST_BUSY; goto exit; } @@ -621,16 +617,16 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, if (sgl_offset == SGL_OFFSET_10) sgl_offset = SGL_OFFSET_12; cmd = I2O_CMD_PRIVATE << 24; - *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC); - *mptr++ = cpu_to_le32(adpt_flags | tid); + writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++); + writel(adpt_flags | tid, mptr++); } #endif - msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); - msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context); + writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]); + writel(i2o_scsi_driver.context, &msg->u.s.icntxt); /* We want the SCSI control block back */ - msg->u.s.tcntxt = cpu_to_le32(i2o_cntxt_list_add(c, SCpnt)); + writel(i2o_cntxt_list_add(c, SCpnt), &msg->u.s.tcntxt); /* LSI_920_PCI_QUIRK * @@ -653,15 +649,15 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, } */ - *mptr++ = cpu_to_le32(scsi_flags | SCpnt->cmd_len); + writel(scsi_flags | SCpnt->cmd_len, mptr++); /* Write SCSI command into the message - always 16 byte block */ - memcpy(mptr, SCpnt->cmnd, 16); + memcpy_toio(mptr, SCpnt->cmnd, 16); mptr += 4; if (sgl_offset != SGL_OFFSET_0) { /* write size of data addressed by SGL */ - *mptr++ = cpu_to_le32(SCpnt->request_bufflen); + writel(SCpnt->request_bufflen, mptr++); /* Now fill in the SGList and command */ if (SCpnt->use_sg) { @@ -680,11 +676,11 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, } /* Stick the headers on */ - msg->u.head[0] = - cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset); + writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset, + &msg->u.head[0]); /* Queue the message */ - i2o_msg_post(c, msg); + i2o_msg_post(c, m); osm_debug("Issued %ld\n", SCpnt->serial_number); @@ -692,7 +688,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, nomem: rc = -ENOMEM; - i2o_msg_nop(c, msg); + i2o_msg_nop(c, m); exit: return rc; @@ -713,7 +709,8 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) { struct i2o_device *i2o_dev; struct i2o_controller *c; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; int tid; int status = FAILED; @@ -723,16 +720,16 @@ static int i2o_scsi_abort(struct scsi_cmnd *SCpnt) c = i2o_dev->iop; tid = i2o_dev->lct_data.tid; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) return SCSI_MLQUEUE_HOST_BUSY; - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid); - msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt)); + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid, + &msg->u.head[1]); + writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]); - if (i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT)) + if (i2o_msg_post_wait(c, m, I2O_TIMEOUT_SCSI_SCB_ABORT)) status = SUCCESS; return status; diff --git a/trunk/drivers/message/i2o/iop.c b/trunk/drivers/message/i2o/iop.c index 492167446936..4eb53258842e 100644 --- a/trunk/drivers/message/i2o/iop.c +++ b/trunk/drivers/message/i2o/iop.c @@ -32,7 +32,7 @@ #include "core.h" #define OSM_NAME "i2o" -#define OSM_VERSION "1.325" +#define OSM_VERSION "1.288" #define OSM_DESCRIPTION "I2O subsystem" /* global I2O controller list */ @@ -46,6 +46,27 @@ static struct i2o_dma i2o_systab; static int i2o_hrt_get(struct i2o_controller *c); +/** + * i2o_msg_nop - Returns a message which is not used + * @c: I2O controller from which the message was created + * @m: message which should be returned + * + * If you fetch a message via i2o_msg_get, and can't use it, you must + * return the message with this function. Otherwise the message frame + * is lost. + */ +void i2o_msg_nop(struct i2o_controller *c, u32 m) +{ + struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m); + + writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(0, &msg->u.head[2]); + writel(0, &msg->u.head[3]); + i2o_msg_post(c, m); +}; + /** * i2o_msg_get_wait - obtain an I2O message from the IOP * @c: I2O controller @@ -60,21 +81,22 @@ static int i2o_hrt_get(struct i2o_controller *c); * address from the read port (see the i2o spec). If no message is * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. */ -struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait) +u32 i2o_msg_get_wait(struct i2o_controller *c, + struct i2o_message __iomem ** msg, int wait) { unsigned long timeout = jiffies + wait * HZ; - struct i2o_message *msg; + u32 m; - while (IS_ERR(msg = i2o_msg_get(c))) { + while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) { if (time_after(jiffies, timeout)) { osm_debug("%s: Timeout waiting for message frame.\n", c->name); - return ERR_PTR(-ETIMEDOUT); + return I2O_QUEUE_EMPTY; } schedule_timeout_uninterruptible(1); } - return msg; + return m; }; #if BITS_PER_LONG == 64 @@ -279,7 +301,8 @@ struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid) */ static int i2o_iop_quiesce(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; i2o_status_block *sb = c->status_block.virt; int rc; @@ -290,17 +313,16 @@ static int i2o_iop_quiesce(struct i2o_controller *c) (sb->iop_state != ADAPTER_STATE_OPERATIONAL)) return 0; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | - ADAPTER_TID); + writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); /* Long timeout needed for quiesce if lots of devices */ - if ((rc = i2o_msg_post_wait(c, msg, 240))) + if ((rc = i2o_msg_post_wait(c, m, 240))) osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc); else osm_debug("%s: Quiesced.\n", c->name); @@ -320,7 +342,8 @@ static int i2o_iop_quiesce(struct i2o_controller *c) */ static int i2o_iop_enable(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; i2o_status_block *sb = c->status_block.virt; int rc; @@ -330,17 +353,16 @@ static int i2o_iop_enable(struct i2o_controller *c) if (sb->iop_state != ADAPTER_STATE_READY) return -EINVAL; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | - ADAPTER_TID); + writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); /* How long of a timeout do we need? */ - if ((rc = i2o_msg_post_wait(c, msg, 240))) + if ((rc = i2o_msg_post_wait(c, m, 240))) osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc); else osm_debug("%s: Enabled.\n", c->name); @@ -391,22 +413,22 @@ static inline void i2o_iop_enable_all(void) */ static int i2o_iop_clear(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; int rc; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; /* Quiesce all IOPs first */ i2o_iop_quiesce_all(); - msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | - ADAPTER_TID); + writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); - if ((rc = i2o_msg_post_wait(c, msg, 30))) + if ((rc = i2o_msg_post_wait(c, m, 30))) osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc); else osm_debug("%s: Cleared.\n", c->name); @@ -424,13 +446,13 @@ static int i2o_iop_clear(struct i2o_controller *c) * Clear and (re)initialize IOP's outbound queue and post the message * frames to the IOP. * - * Returns 0 on success or negative error code on failure. + * Returns 0 on success or a negative errno code on failure. */ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) { - u32 m; volatile u8 *status = c->status.virt; - struct i2o_message *msg; + u32 m; + struct i2o_message __iomem *msg; ulong timeout; int i; @@ -438,24 +460,23 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) memset(c->status.virt, 0, 4); - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); - - msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); - msg->u.s.tcntxt = cpu_to_le32(0x00000000); - msg->body[0] = cpu_to_le32(PAGE_SIZE); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; + + writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]); + writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_exec_driver.context, &msg->u.s.icntxt); + writel(0x00000000, &msg->u.s.tcntxt); + writel(PAGE_SIZE, &msg->body[0]); /* Outbound msg frame size in words and Initcode */ - msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80); - msg->body[2] = cpu_to_le32(0xd0000004); - msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys)); - msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys)); + writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); + writel(0xd0000004, &msg->body[2]); + writel(i2o_dma_low(c->status.phys), &msg->body[3]); + writel(i2o_dma_high(c->status.phys), &msg->body[4]); - i2o_msg_post(c, msg); + i2o_msg_post(c, m); timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ; while (*status <= I2O_CMD_IN_PROGRESS) { @@ -490,34 +511,34 @@ static int i2o_iop_init_outbound_queue(struct i2o_controller *c) static int i2o_iop_reset(struct i2o_controller *c) { volatile u8 *status = c->status.virt; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; unsigned long timeout; i2o_status_block *sb = c->status_block.virt; int rc = 0; osm_debug("%s: Resetting controller\n", c->name); - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; memset(c->status_block.virt, 0, 8); /* Quiesce all IOPs first */ i2o_iop_quiesce_all(); - msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); - msg->u.s.tcntxt = cpu_to_le32(0x00000000); - msg->body[0] = cpu_to_le32(0x00000000); - msg->body[1] = cpu_to_le32(0x00000000); - msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys)); - msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys)); + writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_exec_driver.context, &msg->u.s.icntxt); + writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context + writel(0, &msg->body[0]); + writel(0, &msg->body[1]); + writel(i2o_dma_low(c->status.phys), &msg->body[2]); + writel(i2o_dma_high(c->status.phys), &msg->body[3]); - i2o_msg_post(c, msg); + i2o_msg_post(c, m); /* Wait for a reply */ timeout = jiffies + I2O_TIMEOUT_RESET * HZ; @@ -546,15 +567,18 @@ static int i2o_iop_reset(struct i2o_controller *c) osm_debug("%s: Reset in progress, waiting for reboot...\n", c->name); - while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) { + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); + while (m == I2O_QUEUE_EMPTY) { if (time_after(jiffies, timeout)) { osm_err("%s: IOP reset timeout.\n", c->name); - rc = PTR_ERR(msg); + rc = -ETIMEDOUT; goto exit; } schedule_timeout_uninterruptible(1); + + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET); } - i2o_msg_nop(c, msg); + i2o_msg_nop(c, m); /* from here all quiesce commands are safe */ c->no_quiesce = 0; @@ -662,7 +686,8 @@ static int i2o_iop_activate(struct i2o_controller *c) */ static int i2o_iop_systab_set(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; i2o_status_block *sb = c->status_block.virt; struct device *dev = &c->pdev->dev; struct resource *root; @@ -710,38 +735,41 @@ static int i2o_iop_systab_set(struct i2o_controller *c) } } - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len, PCI_DMA_TODEVICE); if (!i2o_systab.phys) { - i2o_msg_nop(c, msg); + i2o_msg_nop(c, m); return -ENOMEM; } - msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | - ADAPTER_TID); + writel(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6, &msg->u.head[0]); + writel(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); /* * Provide three SGL-elements: * System table (SysTab), Private memory space declaration and * Private i/o space declaration + * + * FIXME: is this still true? + * Nasty one here. We can't use dma_alloc_coherent to send the + * same table to everyone. We have to go remap it for them all */ - msg->body[0] = cpu_to_le32(c->unit + 2); - msg->body[1] = cpu_to_le32(0x00000000); - msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len); - msg->body[3] = cpu_to_le32(i2o_systab.phys); - msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size); - msg->body[5] = cpu_to_le32(sb->current_mem_base); - msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size); - msg->body[6] = cpu_to_le32(sb->current_io_base); + writel(c->unit + 2, &msg->body[0]); + writel(0, &msg->body[1]); + writel(0x54000000 | i2o_systab.len, &msg->body[2]); + writel(i2o_systab.phys, &msg->body[3]); + writel(0x54000000 | sb->current_mem_size, &msg->body[4]); + writel(sb->current_mem_base, &msg->body[5]); + writel(0xd4000000 | sb->current_io_size, &msg->body[6]); + writel(sb->current_io_base, &msg->body[6]); - rc = i2o_msg_post_wait(c, msg, 120); + rc = i2o_msg_post_wait(c, m, 120); dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len, PCI_DMA_TODEVICE); @@ -752,6 +780,8 @@ static int i2o_iop_systab_set(struct i2o_controller *c) else osm_debug("%s: SysTab set.\n", c->name); + i2o_status_get(c); // Entered READY state + return rc; } @@ -761,7 +791,7 @@ static int i2o_iop_systab_set(struct i2o_controller *c) * * Send the system table and enable the I2O controller. * - * Returns 0 on success or negative error code on failure. + * Returns 0 on success or negativer error code on failure. */ static int i2o_iop_online(struct i2o_controller *c) { @@ -800,6 +830,7 @@ void i2o_iop_remove(struct i2o_controller *c) list_for_each_entry_safe(dev, tmp, &c->devices, list) i2o_device_remove(dev); + class_device_unregister(c->classdev); device_del(&c->device); /* Ask the IOP to switch to RESET state */ @@ -838,11 +869,12 @@ static int i2o_systab_build(void) i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers * sizeof(struct i2o_sys_tbl_entry); - systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL); + systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL); if (!systab) { osm_err("unable to allocate memory for System Table\n"); return -ENOMEM; } + memset(systab, 0, i2o_systab.len); systab->version = I2OVERSION; systab->change_ind = change_ind + 1; @@ -920,30 +952,30 @@ static int i2o_parse_hrt(struct i2o_controller *c) */ int i2o_status_get(struct i2o_controller *c) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; volatile u8 *status_block; unsigned long timeout; status_block = (u8 *) c->status_block.virt; memset(c->status_block.virt, 0, sizeof(i2o_status_block)); - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context); - msg->u.s.tcntxt = cpu_to_le32(0x00000000); - msg->body[0] = cpu_to_le32(0x00000000); - msg->body[1] = cpu_to_le32(0x00000000); - msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys)); - msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys)); - msg->body[4] = cpu_to_le32(sizeof(i2o_status_block)); /* always 88 bytes */ + writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(i2o_exec_driver.context, &msg->u.s.icntxt); + writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context + writel(0, &msg->body[0]); + writel(0, &msg->body[1]); + writel(i2o_dma_low(c->status_block.phys), &msg->body[2]); + writel(i2o_dma_high(c->status_block.phys), &msg->body[3]); + writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */ - i2o_msg_post(c, msg); + i2o_msg_post(c, m); /* Wait for a reply */ timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ; @@ -970,7 +1002,7 @@ int i2o_status_get(struct i2o_controller *c) * The HRT contains information about possible hidden devices but is * mostly useless to us. * - * Returns 0 on success or negative error code on failure. + * Returns 0 on success or negativer error code on failure. */ static int i2o_hrt_get(struct i2o_controller *c) { @@ -981,20 +1013,20 @@ static int i2o_hrt_get(struct i2o_controller *c) struct device *dev = &c->pdev->dev; for (i = 0; i < I2O_HRT_GET_TRIES; i++) { - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | - ADAPTER_TID); - msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len); - msg->body[1] = cpu_to_le32(c->hrt.phys); + writel(SIX_WORD_MSG_SIZE | SGL_OFFSET_4, &msg->u.head[0]); + writel(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 | ADAPTER_TID, + &msg->u.head[1]); + writel(0xd0000000 | c->hrt.len, &msg->body[0]); + writel(c->hrt.phys, &msg->body[1]); - rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt); + rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt); if (rc < 0) { osm_err("%s: Unable to get HRT (status=%#x)\n", c->name, @@ -1018,6 +1050,15 @@ static int i2o_hrt_get(struct i2o_controller *c) return -EBUSY; } +/** + * i2o_iop_free - Free the i2o_controller struct + * @c: I2O controller to free + */ +void i2o_iop_free(struct i2o_controller *c) +{ + kfree(c); +}; + /** * i2o_iop_release - release the memory for a I2O controller * @dev: I2O controller which should be released @@ -1032,11 +1073,14 @@ static void i2o_iop_release(struct device *dev) i2o_iop_free(c); }; +/* I2O controller class */ +static struct class *i2o_controller_class; + /** * i2o_iop_alloc - Allocate and initialize a i2o_controller struct * * Allocate the necessary memory for a i2o_controller struct and - * initialize the lists and message mempool. + * initialize the lists. * * Returns a pointer to the I2O controller or a negative error code on * failure. @@ -1045,29 +1089,20 @@ struct i2o_controller *i2o_iop_alloc(void) { static int unit = 0; /* 0 and 1 are NULL IOP and Local Host */ struct i2o_controller *c; - char poolname[32]; - c = kzalloc(sizeof(*c), GFP_KERNEL); + c = kmalloc(sizeof(*c), GFP_KERNEL); if (!c) { osm_err("i2o: Insufficient memory to allocate a I2O controller." "\n"); return ERR_PTR(-ENOMEM); } - - c->unit = unit++; - sprintf(c->name, "iop%d", c->unit); - - snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name); - if (i2o_pool_alloc - (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4, - I2O_MSG_INPOOL_MIN)) { - kfree(c); - return ERR_PTR(-ENOMEM); - }; + memset(c, 0, sizeof(*c)); INIT_LIST_HEAD(&c->devices); spin_lock_init(&c->lock); init_MUTEX(&c->lct_lock); + c->unit = unit++; + sprintf(c->name, "iop%d", c->unit); device_initialize(&c->device); @@ -1102,29 +1137,36 @@ int i2o_iop_add(struct i2o_controller *c) goto iop_reset; } + c->classdev = class_device_create(i2o_controller_class, NULL, MKDEV(0,0), + &c->device, "iop%d", c->unit); + if (IS_ERR(c->classdev)) { + osm_err("%s: could not add controller class\n", c->name); + goto device_del; + } + osm_info("%s: Activating I2O controller...\n", c->name); osm_info("%s: This may take a few minutes if there are many devices\n", c->name); if ((rc = i2o_iop_activate(c))) { osm_err("%s: could not activate controller\n", c->name); - goto device_del; + goto class_del; } osm_debug("%s: building sys table...\n", c->name); if ((rc = i2o_systab_build())) - goto device_del; + goto class_del; osm_debug("%s: online controller...\n", c->name); if ((rc = i2o_iop_online(c))) - goto device_del; + goto class_del; osm_debug("%s: getting LCT...\n", c->name); if ((rc = i2o_exec_lct_get(c))) - goto device_del; + goto class_del; list_add(&c->list, &i2o_controllers); @@ -1134,6 +1176,9 @@ int i2o_iop_add(struct i2o_controller *c) return 0; + class_del: + class_device_unregister(c->classdev); + device_del: device_del(&c->device); @@ -1154,27 +1199,28 @@ int i2o_iop_add(struct i2o_controller *c) * is waited for, or expected. If you do not want further notifications, * call the i2o_event_register again with a evt_mask of 0. * - * Returns 0 on success or negative error code on failure. + * Returns 0 on success or -ETIMEDOUT if no message could be fetched for + * sending the request. */ int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv, int tcntxt, u32 evt_mask) { struct i2o_controller *c = dev->iop; - struct i2o_message *msg; + struct i2o_message __iomem *msg; + u32 m; - msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET); - if (IS_ERR(msg)) - return PTR_ERR(msg); + m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); + if (m == I2O_QUEUE_EMPTY) + return -ETIMEDOUT; - msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0); - msg->u.head[1] = - cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev-> - lct_data.tid); - msg->u.s.icntxt = cpu_to_le32(drv->context); - msg->u.s.tcntxt = cpu_to_le32(tcntxt); - msg->body[0] = cpu_to_le32(evt_mask); + writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]); + writel(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->lct_data. + tid, &msg->u.head[1]); + writel(drv->context, &msg->u.s.icntxt); + writel(tcntxt, &msg->u.s.tcntxt); + writel(evt_mask, &msg->body[0]); - i2o_msg_post(c, msg); + i2o_msg_post(c, m); return 0; }; @@ -1193,8 +1239,14 @@ static int __init i2o_iop_init(void) printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); - if ((rc = i2o_driver_init())) + i2o_controller_class = class_create(THIS_MODULE, "i2o_controller"); + if (IS_ERR(i2o_controller_class)) { + osm_err("can't register class i2o_controller\n"); goto exit; + } + + if ((rc = i2o_driver_init())) + goto class_exit; if ((rc = i2o_exec_init())) goto driver_exit; @@ -1210,6 +1262,9 @@ static int __init i2o_iop_init(void) driver_exit: i2o_driver_exit(); + class_exit: + class_destroy(i2o_controller_class); + exit: return rc; } @@ -1224,6 +1279,7 @@ static void __exit i2o_iop_exit(void) i2o_pci_exit(); i2o_exec_exit(); i2o_driver_exit(); + class_destroy(i2o_controller_class); }; module_init(i2o_iop_init); diff --git a/trunk/drivers/message/i2o/pci.c b/trunk/drivers/message/i2o/pci.c index c5b656cdea7c..ee7075fa1ec3 100644 --- a/trunk/drivers/message/i2o/pci.c +++ b/trunk/drivers/message/i2o/pci.c @@ -339,7 +339,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, pci_name(pdev)); c->pdev = pdev; - c->device.parent = &pdev->dev; + c->device.parent = get_device(&pdev->dev); /* Cards that fall apart if you hit them with large I/O loads... */ if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) { @@ -410,6 +410,8 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, if ((rc = i2o_iop_add(c))) goto uninstall; + get_device(&c->device); + if (i960) pci_write_config_word(i960, 0x42, 0x03ff); @@ -422,6 +424,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, i2o_pci_free(c); free_controller: + put_device(c->device.parent); i2o_iop_free(c); disable: @@ -451,6 +454,7 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev) printk(KERN_INFO "%s: Controller removed.\n", c->name); + put_device(c->device.parent); put_device(&c->device); }; @@ -479,5 +483,4 @@ void __exit i2o_pci_exit(void) { pci_unregister_driver(&i2o_pci_driver); }; - MODULE_DEVICE_TABLE(pci, i2o_pci_ids); diff --git a/trunk/drivers/mmc/mmc_block.c b/trunk/drivers/mmc/mmc_block.c index 8e380c14bf65..abcf19116d70 100644 --- a/trunk/drivers/mmc/mmc_block.c +++ b/trunk/drivers/mmc/mmc_block.c @@ -263,7 +263,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) */ add_disk_randomness(req->rq_disk); blkdev_dequeue_request(req); - end_that_request_last(req, 1); + end_that_request_last(req); } spin_unlock_irq(&md->lock); } while (ret); @@ -289,7 +289,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) add_disk_randomness(req->rq_disk); blkdev_dequeue_request(req); - end_that_request_last(req, 0); + end_that_request_last(req); spin_unlock_irq(&md->lock); return 0; diff --git a/trunk/drivers/net/phy/Kconfig b/trunk/drivers/net/phy/Kconfig index fa39b944bc46..c782a6329805 100644 --- a/trunk/drivers/net/phy/Kconfig +++ b/trunk/drivers/net/phy/Kconfig @@ -6,7 +6,7 @@ menu "PHY device support" config PHYLIB tristate "PHY Device support and infrastructure" - depends on NET_ETHERNET && (BROKEN || !S390) + depends on NET_ETHERNET && (BROKEN || !ARCH_S390) help Ethernet controllers are usually attached to PHY devices. This option provides infrastructure for diff --git a/trunk/drivers/net/plip.c b/trunk/drivers/net/plip.c index 87ee3271b17d..1bd22cd40c75 100644 --- a/trunk/drivers/net/plip.c +++ b/trunk/drivers/net/plip.c @@ -98,6 +98,7 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n" #include #include #include +#include #include #include #include @@ -105,6 +106,7 @@ static const char version[] = "NET3 PLIP version 2.4-parport gniibe@mri.co.jp\n" #include #include #include +#include #include #include #include diff --git a/trunk/drivers/parport/Kconfig b/trunk/drivers/parport/Kconfig index b8241561da45..725a14119f2a 100644 --- a/trunk/drivers/parport/Kconfig +++ b/trunk/drivers/parport/Kconfig @@ -77,7 +77,7 @@ config PARPORT_PC_SUPERIO config PARPORT_PC_PCMCIA tristate "Support for PCMCIA management for PC-style ports" - depends on PCMCIA && PARPORT_PC + depends on PARPORT!=n && (PCMCIA!=n && PARPORT_PC=m && PARPORT_PC || PARPORT_PC=y && PCMCIA) help Say Y here if you need PCMCIA support for your PC-style parallel ports. If unsure, say N. diff --git a/trunk/drivers/parport/daisy.c b/trunk/drivers/parport/daisy.c index 9ee67321b630..075c7eb5c85d 100644 --- a/trunk/drivers/parport/daisy.c +++ b/trunk/drivers/parport/daisy.c @@ -144,9 +144,9 @@ int parport_daisy_init (struct parport *port) add_dev (numdevs++, port, -1); /* Find out the legacy device's IEEE 1284 device ID. */ - deviceid = kmalloc (1024, GFP_KERNEL); + deviceid = kmalloc (1000, GFP_KERNEL); if (deviceid) { - if (parport_device_id (numdevs - 1, deviceid, 1024) > 2) + if (parport_device_id (numdevs - 1, deviceid, 1000) > 2) detected++; kfree (deviceid); @@ -252,7 +252,7 @@ struct pardevice *parport_open (int devnum, const char *name, selected = port->daisy; parport_release (dev); - if (selected != daisy) { + if (selected != port->daisy) { /* No corresponding device. */ parport_unregister_device (dev); return NULL; @@ -344,9 +344,9 @@ static int cpp_daisy (struct parport *port, int cmd) PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE); udelay (1); - s = parport_read_status (port); parport_frob_control (port, PARPORT_CONTROL_STROBE, 0); udelay (1); + s = parport_read_status (port); parport_write_data (port, 0xff); udelay (2); return s; @@ -395,15 +395,15 @@ int parport_daisy_select (struct parport *port, int daisy, int mode) case IEEE1284_MODE_EPP: case IEEE1284_MODE_EPPSL: case IEEE1284_MODE_EPPSWE: - return !(cpp_daisy (port, 0x20 + daisy) & - PARPORT_STATUS_ERROR); + return (cpp_daisy (port, 0x20 + daisy) & + PARPORT_STATUS_ERROR); // For these modes we should switch to ECP mode: case IEEE1284_MODE_ECP: case IEEE1284_MODE_ECPRLE: case IEEE1284_MODE_ECPSWE: - return !(cpp_daisy (port, 0xd0 + daisy) & - PARPORT_STATUS_ERROR); + return (cpp_daisy (port, 0xd0 + daisy) & + PARPORT_STATUS_ERROR); // Nothing was told for BECP in Daisy chain specification. // May be it's wise to use ECP? @@ -413,8 +413,8 @@ int parport_daisy_select (struct parport *port, int daisy, int mode) case IEEE1284_MODE_BYTE: case IEEE1284_MODE_COMPAT: default: - return !(cpp_daisy (port, 0xe0 + daisy) & - PARPORT_STATUS_ERROR); + return (cpp_daisy (port, 0xe0 + daisy) & + PARPORT_STATUS_ERROR); } } @@ -436,7 +436,7 @@ static int select_port (struct parport *port) static int assign_addrs (struct parport *port) { - unsigned char s; + unsigned char s, last_dev; unsigned char daisy; int thisdev = numdevs; int detected; @@ -472,13 +472,10 @@ static int assign_addrs (struct parport *port) } parport_write_data (port, 0x78); udelay (2); - s = parport_read_status (port); + last_dev = 0; /* We've just been speaking to a device, so we + know there must be at least _one_ out there. */ - for (daisy = 0; - (s & (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT)) - == (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT) - && daisy < 4; - ++daisy) { + for (daisy = 0; daisy < 4; daisy++) { parport_write_data (port, daisy); udelay (2); parport_frob_control (port, @@ -488,18 +485,14 @@ static int assign_addrs (struct parport *port) parport_frob_control (port, PARPORT_CONTROL_STROBE, 0); udelay (1); - add_dev (numdevs++, port, daisy); - - /* See if this device thought it was the last in the - * chain. */ - if (!(s & PARPORT_STATUS_BUSY)) + if (last_dev) + /* No more devices. */ break; - /* We are seeing pass through status now. We see - last_dev from next device or if last_dev does not - work status lines from some non-daisy chain - device. */ - s = parport_read_status (port); + last_dev = !(parport_read_status (port) + & PARPORT_STATUS_BUSY); + + add_dev (numdevs++, port, daisy); } parport_write_data (port, 0xff); udelay (2); @@ -508,11 +501,11 @@ static int assign_addrs (struct parport *port) detected); /* Ask the new devices to introduce themselves. */ - deviceid = kmalloc (1024, GFP_KERNEL); + deviceid = kmalloc (1000, GFP_KERNEL); if (!deviceid) return 0; for (daisy = 0; thisdev < numdevs; thisdev++, daisy++) - parport_device_id (thisdev, deviceid, 1024); + parport_device_id (thisdev, deviceid, 1000); kfree (deviceid); return detected; diff --git a/trunk/drivers/parport/ieee1284_ops.c b/trunk/drivers/parport/ieee1284_ops.c index d6c77658231e..ce1e2aad8b10 100644 --- a/trunk/drivers/parport/ieee1284_ops.c +++ b/trunk/drivers/parport/ieee1284_ops.c @@ -165,7 +165,17 @@ size_t parport_ieee1284_read_nibble (struct parport *port, /* Does the error line indicate end of data? */ if (((i & 1) == 0) && (parport_read_status(port) & PARPORT_STATUS_ERROR)) { - goto end_of_data; + port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; + DPRINTK (KERN_DEBUG + "%s: No more nibble data (%d bytes)\n", + port->name, i/2); + + /* Go to reverse idle phase. */ + parport_frob_control (port, + PARPORT_CONTROL_AUTOFD, + PARPORT_CONTROL_AUTOFD); + port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; + break; } /* Event 7: Set nAutoFd low. */ @@ -215,25 +225,18 @@ size_t parport_ieee1284_read_nibble (struct parport *port, byte = nibble; } + i /= 2; /* i is now in bytes */ + if (i == len) { /* Read the last nibble without checking data avail. */ - if (parport_read_status (port) & PARPORT_STATUS_ERROR) { - end_of_data: - DPRINTK (KERN_DEBUG - "%s: No more nibble data (%d bytes)\n", - port->name, i/2); - - /* Go to reverse idle phase. */ - parport_frob_control (port, - PARPORT_CONTROL_AUTOFD, - PARPORT_CONTROL_AUTOFD); - port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; - } + port = port->physport; + if (parport_read_status (port) & PARPORT_STATUS_ERROR) + port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; else - port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL; + port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL; } - return i/2; + return i; #endif /* IEEE1284 support */ } @@ -253,7 +256,17 @@ size_t parport_ieee1284_read_byte (struct parport *port, /* Data available? */ if (parport_read_status (port) & PARPORT_STATUS_ERROR) { - goto end_of_data; + port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; + DPRINTK (KERN_DEBUG + "%s: No more byte data (%Zd bytes)\n", + port->name, count); + + /* Go to reverse idle phase. */ + parport_frob_control (port, + PARPORT_CONTROL_AUTOFD, + PARPORT_CONTROL_AUTOFD); + port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; + break; } /* Event 14: Place data bus in high impedance state. */ @@ -305,20 +318,11 @@ size_t parport_ieee1284_read_byte (struct parport *port, if (count == len) { /* Read the last byte without checking data avail. */ - if (parport_read_status (port) & PARPORT_STATUS_ERROR) { - end_of_data: - DPRINTK (KERN_DEBUG - "%s: No more byte data (%Zd bytes)\n", - port->name, count); - - /* Go to reverse idle phase. */ - parport_frob_control (port, - PARPORT_CONTROL_AUTOFD, - PARPORT_CONTROL_AUTOFD); - port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; - } + port = port->physport; + if (parport_read_status (port) & PARPORT_STATUS_ERROR) + port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; else - port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL; + port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL; } return count; diff --git a/trunk/drivers/parport/parport_pc.c b/trunk/drivers/parport/parport_pc.c index 18e85ccdae67..c6493ad7c0c8 100644 --- a/trunk/drivers/parport/parport_pc.c +++ b/trunk/drivers/parport/parport_pc.c @@ -1169,7 +1169,7 @@ dump_parport_state ("fwd idle", port); /* GCC is not inlining extern inline function later overwriten to non-inline, so we use outlined_ variants here. */ -static const struct parport_operations parport_pc_ops = +static struct parport_operations parport_pc_ops = { .write_data = parport_pc_write_data, .read_data = parport_pc_read_data, @@ -1211,11 +1211,10 @@ static const struct parport_operations parport_pc_ops = static void __devinit show_parconfig_smsc37c669(int io, int key) { int cr1,cr4,cra,cr23,cr26,cr27,i=0; - static const char *const modes[]={ - "SPP and Bidirectional (PS/2)", - "EPP and SPP", - "ECP", - "ECP and EPP" }; + static const char *modes[]={ "SPP and Bidirectional (PS/2)", + "EPP and SPP", + "ECP", + "ECP and EPP" }; outb(key,io); outb(key,io); @@ -1289,7 +1288,7 @@ static void __devinit show_parconfig_smsc37c669(int io, int key) static void __devinit show_parconfig_winbond(int io, int key) { int cr30,cr60,cr61,cr70,cr74,crf0,i=0; - static const char *const modes[] = { + static const char *modes[] = { "Standard (SPP) and Bidirectional(PS/2)", /* 0 */ "EPP-1.9 and SPP", "ECP", @@ -1298,9 +1297,7 @@ static void __devinit show_parconfig_winbond(int io, int key) "EPP-1.7 and SPP", /* 5 */ "undefined!", "ECP and EPP-1.7" }; - static char *const irqtypes[] = { - "pulsed low, high-Z", - "follows nACK" }; + static char *irqtypes[] = { "pulsed low, high-Z", "follows nACK" }; /* The registers are called compatible-PnP because the register layout is modelled after ISA-PnP, the access @@ -2399,8 +2396,7 @@ EXPORT_SYMBOL (parport_pc_unregister_port); /* ITE support maintained by Rich Liu */ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, - int autodma, - const struct parport_pc_via_data *via) + int autodma, struct parport_pc_via_data *via) { short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 }; struct resource *base_res; @@ -2528,8 +2524,7 @@ static struct parport_pc_via_data via_8231_data __devinitdata = { }; static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq, - int autodma, - const struct parport_pc_via_data *via) + int autodma, struct parport_pc_via_data *via) { u8 tmp, tmp2, siofunc; u8 ppcontrol = 0; @@ -2699,9 +2694,8 @@ enum parport_pc_sio_types { /* each element directly indexed from enum list, above */ static struct parport_pc_superio { - int (*probe) (struct pci_dev *pdev, int autoirq, int autodma, - const struct parport_pc_via_data *via); - const struct parport_pc_via_data *via; + int (*probe) (struct pci_dev *pdev, int autoirq, int autodma, struct parport_pc_via_data *via); + struct parport_pc_via_data *via; } parport_pc_superio_info[] __devinitdata = { { sio_via_probe, &via_686a_data, }, { sio_via_probe, &via_8231_data, }, @@ -2834,7 +2828,7 @@ static struct parport_pc_pci { /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ }; -static const struct pci_device_id parport_pc_pci_tbl[] = { +static struct pci_device_id parport_pc_pci_tbl[] = { /* Super-IO onboard chips */ { 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a }, { 0x1106, 0x8231, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_8231 }, diff --git a/trunk/drivers/parport/probe.c b/trunk/drivers/parport/probe.c index b62aee8de3cb..4b48b31ec235 100644 --- a/trunk/drivers/parport/probe.c +++ b/trunk/drivers/parport/probe.c @@ -11,9 +11,9 @@ #include #include -static const struct { - const char *token; - const char *descr; +static struct { + char *token; + char *descr; } classes[] = { { "", "Legacy device" }, { "PRINTER", "Printer" }, @@ -128,131 +128,8 @@ static void parse_data(struct parport *port, int device, char *str) kfree(txt); } -/* Read up to count-1 bytes of device id. Terminate buffer with - * '\0'. Buffer begins with two Device ID length bytes as given by - * device. */ -static ssize_t parport_read_device_id (struct parport *port, char *buffer, - size_t count) -{ - unsigned char length[2]; - unsigned lelen, belen; - size_t idlens[4]; - unsigned numidlens; - unsigned current_idlen; - ssize_t retval; - size_t len; - - /* First two bytes are MSB,LSB of inclusive length. */ - retval = parport_read (port, length, 2); - - if (retval < 0) - return retval; - if (retval != 2) - return -EIO; - - if (count < 2) - return 0; - memcpy(buffer, length, 2); - len = 2; - - /* Some devices wrongly send LE length, and some send it two - * bytes short. Construct a sorted array of lengths to try. */ - belen = (length[0] << 8) + length[1]; - lelen = (length[1] << 8) + length[0]; - idlens[0] = min(belen, lelen); - idlens[1] = idlens[0]+2; - if (belen != lelen) { - int off = 2; - /* Don't try lenghts of 0x100 and 0x200 as 1 and 2 */ - if (idlens[0] <= 2) - off = 0; - idlens[off] = max(belen, lelen); - idlens[off+1] = idlens[off]+2; - numidlens = off+2; - } - else { - /* Some devices don't truly implement Device ID, but - * just return constant nibble forever. This catches - * also those cases. */ - if (idlens[0] == 0 || idlens[0] > 0xFFF) { - printk (KERN_DEBUG "%s: reported broken Device ID" - " length of %#zX bytes\n", - port->name, idlens[0]); - return -EIO; - } - numidlens = 2; - } - - /* Try to respect the given ID length despite all the bugs in - * the ID length. Read according to shortest possible ID - * first. */ - for (current_idlen = 0; current_idlen < numidlens; ++current_idlen) { - size_t idlen = idlens[current_idlen]; - if (idlen+1 >= count) - break; - - retval = parport_read (port, buffer+len, idlen-len); - - if (retval < 0) - return retval; - len += retval; - - if (port->physport->ieee1284.phase != IEEE1284_PH_HBUSY_DAVAIL) { - if (belen != len) { - printk (KERN_DEBUG "%s: Device ID was %d bytes" - " while device told it would be %d" - " bytes\n", - port->name, len, belen); - } - goto done; - } - - /* This might end reading the Device ID too - * soon. Hopefully the needed fields were already in - * the first 256 bytes or so that we must have read so - * far. */ - if (buffer[len-1] == ';') { - printk (KERN_DEBUG "%s: Device ID reading stopped" - " before device told data not available. " - "Current idlen %d of %d, len bytes %02X %02X\n", - port->name, current_idlen, numidlens, - length[0], length[1]); - goto done; - } - } - if (current_idlen < numidlens) { - /* Buffer not large enough, read to end of buffer. */ - size_t idlen, len2; - if (len+1 < count) { - retval = parport_read (port, buffer+len, count-len-1); - if (retval < 0) - return retval; - len += retval; - } - /* Read the whole ID since some devices would not - * otherwise give back the Device ID from beginning - * next time when asked. */ - idlen = idlens[current_idlen]; - len2 = len; - while(len2 < idlen && retval > 0) { - char tmp[4]; - retval = parport_read (port, tmp, - min(sizeof tmp, idlen-len2)); - if (retval < 0) - return retval; - len2 += retval; - } - } - /* In addition, there are broken devices out there that don't - even finish off with a semi-colon. We do not need to care - about those at this time. */ - done: - buffer[len] = '\0'; - return len; -} - /* Get Std 1284 Device ID. */ -ssize_t parport_device_id (int devnum, char *buffer, size_t count) +ssize_t parport_device_id (int devnum, char *buffer, size_t len) { ssize_t retval = -ENXIO; struct pardevice *dev = parport_open (devnum, "Device ID probe", @@ -262,20 +139,76 @@ ssize_t parport_device_id (int devnum, char *buffer, size_t count) parport_claim_or_block (dev); - /* Negotiate to compatibility mode, and then to device ID - * mode. (This so that we start form beginning of device ID if - * already in device ID mode.) */ + /* Negotiate to compatibility mode, and then to device ID mode. + * (This is in case we are already in device ID mode.) */ parport_negotiate (dev->port, IEEE1284_MODE_COMPAT); retval = parport_negotiate (dev->port, IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID); if (!retval) { - retval = parport_read_device_id (dev->port, buffer, count); + int idlen; + unsigned char length[2]; + + /* First two bytes are MSB,LSB of inclusive length. */ + retval = parport_read (dev->port, length, 2); + + if (retval != 2) goto end_id; + + idlen = (length[0] << 8) + length[1] - 2; + /* + * Check if the caller-allocated buffer is large enough + * otherwise bail out or there will be an at least off by one. + */ + if (idlen + 1 < len) + len = idlen; + else { + retval = -EINVAL; + goto out; + } + retval = parport_read (dev->port, buffer, len); + + if (retval != len) + printk (KERN_DEBUG "%s: only read %Zd of %Zd ID bytes\n", + dev->port->name, retval, + len); + + /* Some printer manufacturers mistakenly believe that + the length field is supposed to be _exclusive_. + In addition, there are broken devices out there + that don't even finish off with a semi-colon. */ + if (buffer[len - 1] != ';') { + ssize_t diff; + diff = parport_read (dev->port, buffer + len, 2); + retval += diff; + + if (diff) + printk (KERN_DEBUG + "%s: device reported incorrect " + "length field (%d, should be %Zd)\n", + dev->port->name, idlen, retval); + else { + /* One semi-colon short of a device ID. */ + buffer[len++] = ';'; + printk (KERN_DEBUG "%s: faking semi-colon\n", + dev->port->name); + + /* If we get here, I don't think we + need to worry about the possible + standard violation of having read + more than we were told to. The + device is non-compliant anyhow. */ + } + } + + end_id: + buffer[len] = '\0'; parport_negotiate (dev->port, IEEE1284_MODE_COMPAT); - if (retval > 2) - parse_data (dev->port, dev->daisy, buffer+2); } + if (retval > 2) + parse_data (dev->port, dev->daisy, buffer); + +out: parport_release (dev); parport_close (dev); return retval; diff --git a/trunk/drivers/parport/share.c b/trunk/drivers/parport/share.c index ea62bed6bc83..9cb3ab156b09 100644 --- a/trunk/drivers/parport/share.c +++ b/trunk/drivers/parport/share.c @@ -1002,7 +1002,6 @@ EXPORT_SYMBOL(parport_register_driver); EXPORT_SYMBOL(parport_unregister_driver); EXPORT_SYMBOL(parport_register_device); EXPORT_SYMBOL(parport_unregister_device); -EXPORT_SYMBOL(parport_get_port); EXPORT_SYMBOL(parport_put_port); EXPORT_SYMBOL(parport_find_number); EXPORT_SYMBOL(parport_find_base); diff --git a/trunk/drivers/pnp/pnpbios/bioscalls.c b/trunk/drivers/pnp/pnpbios/bioscalls.c index a1f0b0ba2bfe..6b7583f497d0 100644 --- a/trunk/drivers/pnp/pnpbios/bioscalls.c +++ b/trunk/drivers/pnp/pnpbios/bioscalls.c @@ -31,6 +31,15 @@ static struct { } pnp_bios_callpoint; +/* The PnP BIOS entries in the GDT */ +#define PNP_GDT (GDT_ENTRY_PNPBIOS_BASE * 8) + +#define PNP_CS32 (PNP_GDT+0x00) /* segment for calling fn */ +#define PNP_CS16 (PNP_GDT+0x08) /* code segment for BIOS */ +#define PNP_DS (PNP_GDT+0x10) /* data segment for BIOS */ +#define PNP_TS1 (PNP_GDT+0x18) /* transfer data segment */ +#define PNP_TS2 (PNP_GDT+0x20) /* another data segment */ + /* * These are some opcodes for a "static asmlinkage" * As this code is *not* executed inside the linux kernel segment, but in a @@ -58,11 +67,16 @@ __asm__( ".previous \n" ); +#define Q_SET_SEL(cpu, selname, address, size) \ +do { \ +set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], __va((u32)(address))); \ +set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \ +} while(0) + #define Q2_SET_SEL(cpu, selname, address, size) \ do { \ -struct desc_struct *gdt = get_cpu_gdt_table((cpu)); \ -set_base(gdt[(selname) >> 3], (u32)(address)); \ -set_limit(gdt[(selname) >> 3], size); \ +set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], (u32)(address)); \ +set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \ } while(0) static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; @@ -101,8 +115,8 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, return PNP_FUNCTION_NOT_SUPPORTED; cpu = get_cpu(); - save_desc_40 = get_cpu_gdt_table(cpu)[0x40 / 8]; - get_cpu_gdt_table(cpu)[0x40 / 8] = bad_bios_desc; + save_desc_40 = per_cpu(cpu_gdt_table,cpu)[0x40 / 8]; + per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = bad_bios_desc; /* On some boxes IRQ's during PnP BIOS calls are deadly. */ spin_lock_irqsave(&pnp_bios_lock, flags); @@ -144,7 +158,7 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, ); spin_unlock_irqrestore(&pnp_bios_lock, flags); - get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40; + per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = save_desc_40; put_cpu(); /* If we get here and this is set then the PnP BIOS faulted on us. */ @@ -276,15 +290,12 @@ int pnp_bios_dev_node_info(struct pnp_dev_node_info *data) static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data) { u16 status; - u16 tmp_nodenum; if (!pnp_bios_present()) return PNP_FUNCTION_NOT_SUPPORTED; if ( !boot && pnpbios_dont_use_current_config ) return PNP_FUNCTION_NOT_SUPPORTED; - tmp_nodenum = *nodenum; status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0, - &tmp_nodenum, sizeof(tmp_nodenum), data, 65536); - *nodenum = tmp_nodenum; + nodenum, sizeof(char), data, 65536); return status; } @@ -524,12 +535,10 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); - for (i = 0; i < NR_CPUS; i++) { - struct desc_struct *gdt = get_cpu_gdt_table(i); - if (!gdt) - continue; - set_base(gdt[GDT_ENTRY_PNPBIOS_CS32], &pnp_bios_callfunc); - set_base(gdt[GDT_ENTRY_PNPBIOS_CS16], __va(header->fields.pm16cseg)); - set_base(gdt[GDT_ENTRY_PNPBIOS_DS], __va(header->fields.pm16dseg)); - } + for(i=0; i < NR_CPUS; i++) + { + Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024); + Q_SET_SEL(i, PNP_CS16, header->fields.pm16cseg, 64 * 1024); + Q_SET_SEL(i, PNP_DS, header->fields.pm16dseg, 64 * 1024); + } } diff --git a/trunk/drivers/s390/Makefile b/trunk/drivers/s390/Makefile index 9803c9352d78..c99a2fe92fb0 100644 --- a/trunk/drivers/s390/Makefile +++ b/trunk/drivers/s390/Makefile @@ -2,7 +2,7 @@ # Makefile for the S/390 specific device drivers # -obj-y += s390mach.o sysinfo.o s390_rdev.o +obj-y += s390mach.o sysinfo.o obj-y += cio/ block/ char/ crypto/ net/ scsi/ drivers-y += drivers/s390/built-in.o diff --git a/trunk/drivers/s390/block/Kconfig b/trunk/drivers/s390/block/Kconfig index 6f50cc9323d9..6e7d7b06421d 100644 --- a/trunk/drivers/s390/block/Kconfig +++ b/trunk/drivers/s390/block/Kconfig @@ -1,11 +1,11 @@ -if S390 +if ARCH_S390 comment "S/390 block device drivers" - depends on S390 + depends on ARCH_S390 config BLK_DEV_XPRAM tristate "XPRAM disk support" - depends on S390 + depends on ARCH_S390 help Select this option if you want to use your expanded storage on S/390 or zSeries as a disk. This is useful as a _fast_ swap device if you @@ -49,7 +49,7 @@ config DASD_FBA config DASD_DIAG tristate "Support for DIAG access to Disks" - depends on DASD && ( 64BIT = 'n' || EXPERIMENTAL) + depends on DASD && ( ARCH_S390X = 'n' || EXPERIMENTAL) help Select this option if you want to use Diagnose250 command to access Disks under VM. If you are not running under VM or unsure what it is, diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index f779f674dfa0..7008d32433bf 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.172 $ + * $Revision: 1.167 $ */ #include @@ -604,7 +604,7 @@ dasd_smalloc_request(char *magic, int cplength, int datasize, void dasd_kfree_request(struct dasd_ccw_req * cqr, struct dasd_device * device) { -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X struct ccw1 *ccw; /* Clear any idals used for the request. */ @@ -1035,7 +1035,7 @@ dasd_end_request(struct request *req, int uptodate) if (end_that_request_first(req, uptodate, req->hard_nr_sectors)) BUG(); add_disk_randomness(req->rq_disk); - end_that_request_last(req, uptodate); + end_that_request_last(req); } /* @@ -1224,12 +1224,6 @@ __dasd_start_head(struct dasd_device * device) if (list_empty(&device->ccw_queue)) return; cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); - /* check FAILFAST */ - if (device->stopped & ~DASD_STOPPED_PENDING && - test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags)) { - cqr->status = DASD_CQR_FAILED; - dasd_schedule_bh(device); - } if ((cqr->status == DASD_CQR_QUEUED) && (!device->stopped)) { /* try to start the first I/O that can be started */ @@ -1329,7 +1323,7 @@ void dasd_schedule_bh(struct dasd_device * device) { /* Protect against rescheduling. */ - if (atomic_cmpxchg (&device->tasklet_scheduled, 0, 1) != 0) + if (atomic_compare_and_swap (0, 1, &device->tasklet_scheduled)) return; dasd_get_device(device); tasklet_hi_schedule(&device->tasklet); @@ -1756,10 +1750,8 @@ dasd_exit(void) * SECTION: common functions for ccw_driver use */ -/* - * Initial attempt at a probe function. this can be simplified once - * the other detection code is gone. - */ +/* initial attempt at a probe function. this can be simplified once + * the other detection code is gone */ int dasd_generic_probe (struct ccw_device *cdev, struct dasd_discipline *discipline) @@ -1778,10 +1770,8 @@ dasd_generic_probe (struct ccw_device *cdev, return ret; } -/* - * This will one day be called from a global not_oper handler. - * It is also used by driver_unregister during module unload. - */ +/* this will one day be called from a global not_oper handler. + * It is also used by driver_unregister during module unload */ void dasd_generic_remove (struct ccw_device *cdev) { @@ -1808,11 +1798,9 @@ dasd_generic_remove (struct ccw_device *cdev) dasd_delete_device(device); } -/* - * Activate a device. This is called from dasd_{eckd,fba}_probe() when either +/* activate a device. This is called from dasd_{eckd,fba}_probe() when either * the device is detected for the first time and is supposed to be used - * or the user has started activation through sysfs. - */ + * or the user has started activation through sysfs */ int dasd_generic_set_online (struct ccw_device *cdev, struct dasd_discipline *discipline) @@ -1929,6 +1917,7 @@ dasd_generic_notify(struct ccw_device *cdev, int event) if (cqr->status == DASD_CQR_IN_IO) cqr->status = DASD_CQR_FAILED; device->stopped |= DASD_STOPPED_DC_EIO; + dasd_schedule_bh(device); } else { list_for_each_entry(cqr, &device->ccw_queue, list) if (cqr->status == DASD_CQR_IN_IO) { @@ -1938,7 +1927,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event) device->stopped |= DASD_STOPPED_DC_WAIT; dasd_set_timer(device, 0); } - dasd_schedule_bh(device); ret = 1; break; case CIO_OPER: diff --git a/trunk/drivers/s390/block/dasd_diag.c b/trunk/drivers/s390/block/dasd_diag.c index ba80fdea7ebf..ab8754e566bc 100644 --- a/trunk/drivers/s390/block/dasd_diag.c +++ b/trunk/drivers/s390/block/dasd_diag.c @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.53 $ + * $Revision: 1.51 $ */ #include @@ -25,7 +25,6 @@ #include #include #include -#include #include "dasd_int.h" #include "dasd_diag.h" @@ -75,7 +74,7 @@ dia250(void *iob, int cmd) int rc; __asm__ __volatile__( -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X " lghi %0,3\n" " lgr 0,%3\n" " diag 0,%2,0x250\n" @@ -330,7 +329,7 @@ dasd_diag_check_device(struct dasd_device *device) struct dasd_diag_private *private; struct dasd_diag_characteristics *rdc_data; struct dasd_diag_bio bio; - struct vtoc_cms_label *label; + struct dasd_diag_cms_label *label; blocknum_t end_block; unsigned int sb, bsize; int rc; @@ -381,7 +380,7 @@ dasd_diag_check_device(struct dasd_device *device) mdsk_term_io(device); /* figure out blocksize of device */ - label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL); + label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL); if (label == NULL) { DEV_MESSAGE(KERN_WARNING, device, "%s", "No memory to allocate initialization request"); @@ -549,8 +548,6 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) } cqr->retries = DIAG_MAX_RETRIES; cqr->buildclk = get_clock(); - if (req->flags & REQ_FAILFAST) - set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); cqr->device = device; cqr->expires = DIAG_TIMEOUT; cqr->status = DASD_CQR_FILLED; diff --git a/trunk/drivers/s390/block/dasd_diag.h b/trunk/drivers/s390/block/dasd_diag.h index a4f80bd735f1..df31484d73a7 100644 --- a/trunk/drivers/s390/block/dasd_diag.h +++ b/trunk/drivers/s390/block/dasd_diag.h @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.9 $ + * $Revision: 1.8 $ */ #define MDSK_WRITE_REQ 0x01 @@ -44,8 +44,29 @@ struct dasd_diag_characteristics { u8 rdev_features; } __attribute__ ((packed, aligned(4))); - -#ifdef CONFIG_64BIT +struct dasd_diag_cms_label { + u8 label_id[4]; + u8 vol_id[6]; + u16 version_id; + u32 block_size; + u32 origin_ptr; + u32 usable_count; + u32 formatted_count; + u32 block_count; + u32 used_count; + u32 fst_size; + u32 fst_count; + u8 format_date[6]; + u8 reserved1[2]; + u32 disk_offset; + u32 map_block; + u32 hblk_disp; + u32 user_disp; + u8 reserved2[4]; + u8 segment_name[8]; +} __attribute__ ((packed)); + +#ifdef CONFIG_ARCH_S390X #define DASD_DIAG_FLAGA_DEFAULT DASD_DIAG_FLAGA_FORMAT_64BIT typedef u64 blocknum_t; @@ -86,7 +107,7 @@ struct dasd_diag_rw_io { struct dasd_diag_bio *bio_list; u8 spare4[8]; } __attribute__ ((packed, aligned(8))); -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ #define DASD_DIAG_FLAGA_DEFAULT 0x0 typedef u32 blocknum_t; @@ -125,4 +146,4 @@ struct dasd_diag_rw_io { u32 interrupt_params; u8 spare3[20]; } __attribute__ ((packed, aligned(8))); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index 96eb48258580..811060e10c00 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.74 $ + * $Revision: 1.71 $ */ #include @@ -1041,7 +1041,7 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) /* Eckd can only do full blocks. */ return ERR_PTR(-EINVAL); count += bv->bv_len >> (device->s2b_shift + 9); -#if defined(CONFIG_64BIT) +#if defined(CONFIG_ARCH_S390X) if (idal_is_needed (page_address(bv->bv_page), bv->bv_len)) cidaw += bv->bv_len >> (device->s2b_shift + 9); @@ -1136,8 +1136,6 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) recid++; } } - if (req->flags & REQ_FAILFAST) - set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); cqr->device = device; cqr->expires = 5 * 60 * HZ; /* 5 minutes */ cqr->lpm = private->path_data.ppm; @@ -1254,7 +1252,6 @@ dasd_eckd_release(struct block_device *bdev, int no, long args) cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; cqr->device = device; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); - set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); cqr->retries = 0; cqr->expires = 2 * HZ; cqr->buildclk = get_clock(); @@ -1299,7 +1296,6 @@ dasd_eckd_reserve(struct block_device *bdev, int no, long args) cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; cqr->device = device; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); - set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); cqr->retries = 0; cqr->expires = 2 * HZ; cqr->buildclk = get_clock(); @@ -1343,7 +1339,6 @@ dasd_eckd_steal_lock(struct block_device *bdev, int no, long args) cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; cqr->device = device; clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); - set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); cqr->retries = 0; cqr->expires = 2 * HZ; cqr->buildclk = get_clock(); diff --git a/trunk/drivers/s390/block/dasd_fba.c b/trunk/drivers/s390/block/dasd_fba.c index 8ec75dc08e2c..28cb4613b7f5 100644 --- a/trunk/drivers/s390/block/dasd_fba.c +++ b/trunk/drivers/s390/block/dasd_fba.c @@ -4,7 +4,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.41 $ + * $Revision: 1.40 $ */ #include @@ -271,7 +271,7 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) /* Fba can only do full blocks. */ return ERR_PTR(-EINVAL); count += bv->bv_len >> (device->s2b_shift + 9); -#if defined(CONFIG_64BIT) +#if defined(CONFIG_ARCH_S390X) if (idal_is_needed (page_address(bv->bv_page), bv->bv_len)) cidaw += bv->bv_len / blksize; @@ -352,8 +352,6 @@ dasd_fba_build_cp(struct dasd_device * device, struct request *req) recid++; } } - if (req->flags & REQ_FAILFAST) - set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); cqr->device = device; cqr->expires = 5 * 60 * HZ; /* 5 minutes */ cqr->retries = 32; diff --git a/trunk/drivers/s390/block/dasd_int.h b/trunk/drivers/s390/block/dasd_int.h index 2fb05c4a528c..9fab04f3056d 100644 --- a/trunk/drivers/s390/block/dasd_int.h +++ b/trunk/drivers/s390/block/dasd_int.h @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.68 $ + * $Revision: 1.65 $ */ #ifndef DASD_INT_H @@ -208,7 +208,6 @@ struct dasd_ccw_req { /* per dasd_ccw_req flags */ #define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ -#define DASD_CQR_FLAGS_FAILFAST 1 /* FAILFAST */ /* Signature for error recovery functions. */ typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); diff --git a/trunk/drivers/s390/block/dasd_ioctl.c b/trunk/drivers/s390/block/dasd_ioctl.c index 044b75371990..789595b3fa09 100644 --- a/trunk/drivers/s390/block/dasd_ioctl.c +++ b/trunk/drivers/s390/block/dasd_ioctl.c @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.50 $ + * $Revision: 1.47 $ * * i/o controls for the dasd driver. */ @@ -352,9 +352,6 @@ dasd_ioctl_read_profile(struct block_device *bdev, int no, long args) if (device == NULL) return -ENODEV; - if (dasd_profile_level == DASD_PROFILE_OFF) - return -EIO; - if (copy_to_user((long __user *) args, (long *) &device->profile, sizeof (struct dasd_profile_info_t))) return -EFAULT; diff --git a/trunk/drivers/s390/block/dcssblk.c b/trunk/drivers/s390/block/dcssblk.c index 2e727f49ad19..4fde41188996 100644 --- a/trunk/drivers/s390/block/dcssblk.c +++ b/trunk/drivers/s390/block/dcssblk.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include // for s390_root_dev_(un)register() //#define DCSSBLK_DEBUG /* Debug messages on/off */ #define DCSSBLK_NAME "dcssblk" diff --git a/trunk/drivers/s390/block/xpram.c b/trunk/drivers/s390/block/xpram.c index bf3a67c3cc5e..d428c909b8a0 100644 --- a/trunk/drivers/s390/block/xpram.c +++ b/trunk/drivers/s390/block/xpram.c @@ -160,7 +160,7 @@ static int xpram_page_in (unsigned long page_addr, unsigned int xpage_index) "0: ipm %0\n" " srl %0,28\n" "1:\n" -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X ".section __ex_table,\"a\"\n" " .align 4\n" " .long 0b,1b\n" @@ -208,7 +208,7 @@ static long xpram_page_out (unsigned long page_addr, unsigned int xpage_index) "0: ipm %0\n" " srl %0,28\n" "1:\n" -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X ".section __ex_table,\"a\"\n" " .align 4\n" " .long 0b,1b\n" diff --git a/trunk/drivers/s390/char/sclp_cpi.c b/trunk/drivers/s390/char/sclp_cpi.c index 80f7f31310e6..5a6cef2dfa13 100644 --- a/trunk/drivers/s390/char/sclp_cpi.c +++ b/trunk/drivers/s390/char/sclp_cpi.c @@ -204,7 +204,7 @@ cpi_module_init(void) printk(KERN_WARNING "cpi: no control program identification " "support\n"); sclp_unregister(&sclp_cpi_event); - return -EOPNOTSUPP; + return -ENOTSUPP; } req = cpi_prepare_req(); diff --git a/trunk/drivers/s390/char/sclp_quiesce.c b/trunk/drivers/s390/char/sclp_quiesce.c index 56fa69168898..83f75774df60 100644 --- a/trunk/drivers/s390/char/sclp_quiesce.c +++ b/trunk/drivers/s390/char/sclp_quiesce.c @@ -32,7 +32,7 @@ do_load_quiesce_psw(void * __unused) psw_t quiesce_psw; int cpu; - if (atomic_cmpxchg(&cpuid, -1, smp_processor_id()) != -1) + if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid)) signal_processor(smp_processor_id(), sigp_stop); /* Wait for all other cpus to enter stopped state */ for_each_online_cpu(cpu) { diff --git a/trunk/drivers/s390/char/tape_block.c b/trunk/drivers/s390/char/tape_block.c index 5ced2725d6c7..1efc9f21229e 100644 --- a/trunk/drivers/s390/char/tape_block.c +++ b/trunk/drivers/s390/char/tape_block.c @@ -65,7 +65,7 @@ static void tapeblock_trigger_requeue(struct tape_device *device) { /* Protect against rescheduling. */ - if (atomic_cmpxchg(&device->blk_data.requeue_scheduled, 0, 1) != 0) + if (atomic_compare_and_swap(0, 1, &device->blk_data.requeue_scheduled)) return; schedule_work(&device->blk_data.requeue_task); } @@ -78,7 +78,7 @@ tapeblock_end_request(struct request *req, int uptodate) { if (end_that_request_first(req, uptodate, req->hard_nr_sectors)) BUG(); - end_that_request_last(req, uptodate); + end_that_request_last(req); } static void diff --git a/trunk/drivers/s390/char/vmwatchdog.c b/trunk/drivers/s390/char/vmwatchdog.c index 5acc0ace3d7d..5473c23fcb52 100644 --- a/trunk/drivers/s390/char/vmwatchdog.c +++ b/trunk/drivers/s390/char/vmwatchdog.c @@ -66,7 +66,7 @@ static int __diag288(enum vmwdt_func func, unsigned int timeout, __cmdl = len; err = 0; asm volatile ( -#ifdef CONFIG_64BIT +#ifdef __s390x__ "diag %2,%4,0x288\n" "1: \n" ".section .fixup,\"ax\"\n" diff --git a/trunk/drivers/s390/cio/blacklist.c b/trunk/drivers/s390/cio/blacklist.c index daf21e03b21d..a1c52a682191 100644 --- a/trunk/drivers/s390/cio/blacklist.c +++ b/trunk/drivers/s390/cio/blacklist.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/blacklist.c * S/390 common I/O routines -- blacklisting of specific devices - * $Revision: 1.39 $ + * $Revision: 1.35 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -35,10 +34,10 @@ * These can be single devices or ranges of devices */ -/* 65536 bits for each set to indicate if a devno is blacklisted or not */ -#define __BL_DEV_WORDS ((__MAX_SUBCHANNEL + (8*sizeof(long) - 1)) / \ +/* 65536 bits to indicate if a devno is blacklisted or not */ +#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \ (8*sizeof(long))) -static unsigned long bl_dev[__MAX_SSID + 1][__BL_DEV_WORDS]; +static unsigned long bl_dev[__BL_DEV_WORDS]; typedef enum {add, free} range_action; /* @@ -46,23 +45,21 @@ typedef enum {add, free} range_action; * (Un-)blacklist the devices from-to */ static inline void -blacklist_range (range_action action, unsigned int from, unsigned int to, - unsigned int ssid) +blacklist_range (range_action action, unsigned int from, unsigned int to) { if (!to) to = from; - if (from > to || to > __MAX_SUBCHANNEL || ssid > __MAX_SSID) { + if (from > to || to > __MAX_SUBCHANNELS) { printk (KERN_WARNING "Invalid blacklist range " - "0.%x.%04x to 0.%x.%04x, skipping\n", - ssid, from, ssid, to); + "0x%04x to 0x%04x, skipping\n", from, to); return; } for (; from <= to; from++) { if (action == add) - set_bit (from, bl_dev[ssid]); + set_bit (from, bl_dev); else - clear_bit (from, bl_dev[ssid]); + clear_bit (from, bl_dev); } } @@ -72,7 +69,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to, * Shamelessly grabbed from dasd_devmap.c. */ static inline int -blacklist_busid(char **str, int *id0, int *ssid, int *devno) +blacklist_busid(char **str, int *id0, int *id1, int *devno) { int val, old_style; char *sav; @@ -89,7 +86,7 @@ blacklist_busid(char **str, int *id0, int *ssid, int *devno) goto confused; val = simple_strtoul(*str, str, 16); if (old_style || (*str)[0] != '.') { - *id0 = *ssid = 0; + *id0 = *id1 = 0; if (val < 0 || val > 0xffff) goto confused; *devno = val; @@ -108,7 +105,7 @@ blacklist_busid(char **str, int *id0, int *ssid, int *devno) val = simple_strtoul(*str, str, 16); if (val < 0 || val > 0xff || (*str)++[0] != '.') goto confused; - *ssid = val; + *id1 = val; if (!isxdigit((*str)[0])) /* We require at least one hex digit */ goto confused; val = simple_strtoul(*str, str, 16); @@ -128,7 +125,7 @@ blacklist_busid(char **str, int *id0, int *ssid, int *devno) static inline int blacklist_parse_parameters (char *str, range_action action) { - unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid; + unsigned int from, to, from_id0, to_id0, from_id1, to_id1; while (*str != 0 && *str != '\n') { range_action ra = action; @@ -145,25 +142,23 @@ blacklist_parse_parameters (char *str, range_action action) */ if (strncmp(str,"all,",4) == 0 || strcmp(str,"all") == 0 || strncmp(str,"all\n",4) == 0 || strncmp(str,"all ",4) == 0) { - int j; - + from = 0; + to = __MAX_SUBCHANNELS; str += 3; - for (j=0; j <= __MAX_SSID; j++) - blacklist_range(ra, 0, __MAX_SUBCHANNEL, j); } else { int rc; rc = blacklist_busid(&str, &from_id0, - &from_ssid, &from); + &from_id1, &from); if (rc) continue; to = from; to_id0 = from_id0; - to_ssid = from_ssid; + to_id1 = from_id1; if (*str == '-') { str++; rc = blacklist_busid(&str, &to_id0, - &to_ssid, &to); + &to_id1, &to); if (rc) continue; } @@ -173,19 +168,18 @@ blacklist_parse_parameters (char *str, range_action action) strsep(&str, ",\n")); continue; } - if ((from_id0 != to_id0) || - (from_ssid != to_ssid)) { + if ((from_id0 != to_id0) || (from_id1 != to_id1)) { printk(KERN_WARNING "invalid cio_ignore range " "%x.%x.%04x-%x.%x.%04x\n", - from_id0, from_ssid, from, - to_id0, to_ssid, to); + from_id0, from_id1, from, + to_id0, to_id1, to); continue; } - pr_debug("blacklist_setup: adding range " - "from %x.%x.%04x to %x.%x.%04x\n", - from_id0, from_ssid, from, to_id0, to_ssid, to); - blacklist_range (ra, from, to, to_ssid); } + /* FIXME: ignoring id0 and id1 here. */ + pr_debug("blacklist_setup: adding range " + "from 0.0.%04x to 0.0.%04x\n", from, to); + blacklist_range (ra, from, to); } return 1; } @@ -219,33 +213,12 @@ __setup ("cio_ignore=", blacklist_setup); * Used by validate_subchannel() */ int -is_blacklisted (int ssid, int devno) +is_blacklisted (int devno) { - return test_bit (devno, bl_dev[ssid]); + return test_bit (devno, bl_dev); } #ifdef CONFIG_PROC_FS -static int -__s390_redo_validation(struct subchannel_id schid, void *data) -{ - int ret; - struct subchannel *sch; - - sch = get_subchannel_by_schid(schid); - if (sch) { - /* Already known. */ - put_device(&sch->dev); - return 0; - } - ret = css_probe_device(schid); - if (ret == -ENXIO) - return ret; /* We're through. */ - if (ret == -ENOMEM) - /* Stop validation for now. Bad, but no need for a panic. */ - return ret; - return 0; -} - /* * Function: s390_redo_validation * Look for no longer blacklisted devices @@ -253,9 +226,29 @@ __s390_redo_validation(struct subchannel_id schid, void *data) static inline void s390_redo_validation (void) { - CIO_TRACE_EVENT (0, "redoval"); + unsigned int irq; - for_each_subchannel(__s390_redo_validation, NULL); + CIO_TRACE_EVENT (0, "redoval"); + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { + int ret; + struct subchannel *sch; + + sch = get_subchannel_by_schid(irq); + if (sch) { + /* Already known. */ + put_device(&sch->dev); + continue; + } + ret = css_probe_device(irq); + if (ret == -ENXIO) + break; /* We're through. */ + if (ret == -ENOMEM) + /* + * Stop validation for now. Bad, but no need for a + * panic. + */ + break; + } } /* @@ -285,90 +278,41 @@ blacklist_parse_proc_parameters (char *buf) s390_redo_validation (); } -/* Iterator struct for all devices. */ -struct ccwdev_iter { - int devno; - int ssid; - int in_range; -}; - -static void * -cio_ignore_proc_seq_start(struct seq_file *s, loff_t *offset) -{ - struct ccwdev_iter *iter; - - if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1)) - return NULL; - iter = kzalloc(sizeof(struct ccwdev_iter), GFP_KERNEL); - if (!iter) - return ERR_PTR(-ENOMEM); - iter->ssid = *offset / (__MAX_SUBCHANNEL + 1); - iter->devno = *offset % (__MAX_SUBCHANNEL + 1); - return iter; -} - -static void -cio_ignore_proc_seq_stop(struct seq_file *s, void *it) -{ - if (!IS_ERR(it)) - kfree(it); -} - -static void * -cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset) +/* FIXME: These should be real bus ids and not home-grown ones! */ +static int cio_ignore_read (char *page, char **start, off_t off, + int count, int *eof, void *data) { - struct ccwdev_iter *iter; - - if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1)) - return NULL; - iter = it; - if (iter->devno == __MAX_SUBCHANNEL) { - iter->devno = 0; - iter->ssid++; - if (iter->ssid > __MAX_SSID) - return NULL; - } else - iter->devno++; - (*offset)++; - return iter; -} - -static int -cio_ignore_proc_seq_show(struct seq_file *s, void *it) -{ - struct ccwdev_iter *iter; - - iter = it; - if (!is_blacklisted(iter->ssid, iter->devno)) - /* Not blacklisted, nothing to output. */ - return 0; - if (!iter->in_range) { - /* First device in range. */ - if ((iter->devno == __MAX_SUBCHANNEL) || - !is_blacklisted(iter->ssid, iter->devno + 1)) - /* Singular device. */ - return seq_printf(s, "0.%x.%04x\n", - iter->ssid, iter->devno); - iter->in_range = 1; - return seq_printf(s, "0.%x.%04x-", iter->ssid, iter->devno); - } - if ((iter->devno == __MAX_SUBCHANNEL) || - !is_blacklisted(iter->ssid, iter->devno + 1)) { - /* Last device in range. */ - iter->in_range = 0; - return seq_printf(s, "0.%x.%04x\n", iter->ssid, iter->devno); + const unsigned int entry_size = 18; /* "0.0.ABCD-0.0.EFGH\n" */ + long devno; + int len; + + len = 0; + for (devno = off; /* abuse the page variable + * as counter, see fs/proc/generic.c */ + devno < __MAX_SUBCHANNELS && len + entry_size < count; devno++) { + if (!test_bit(devno, bl_dev)) + continue; + len += sprintf(page + len, "0.0.%04lx", devno); + if (test_bit(devno + 1, bl_dev)) { /* print range */ + while (++devno < __MAX_SUBCHANNELS) + if (!test_bit(devno, bl_dev)) + break; + len += sprintf(page + len, "-0.0.%04lx", --devno); + } + len += sprintf(page + len, "\n"); } - return 0; + + if (devno < __MAX_SUBCHANNELS) + *eof = 1; + *start = (char *) (devno - off); /* number of checked entries */ + return len; } -static ssize_t -cio_ignore_write(struct file *file, const char __user *user_buf, - size_t user_len, loff_t *offset) +static int cio_ignore_write(struct file *file, const char __user *user_buf, + unsigned long user_len, void *data) { char *buf; - if (*offset) - return -EINVAL; if (user_len > 65536) user_len = 65536; buf = vmalloc (user_len + 1); /* maybe better use the stack? */ @@ -386,27 +330,6 @@ cio_ignore_write(struct file *file, const char __user *user_buf, return user_len; } -static struct seq_operations cio_ignore_proc_seq_ops = { - .start = cio_ignore_proc_seq_start, - .stop = cio_ignore_proc_seq_stop, - .next = cio_ignore_proc_seq_next, - .show = cio_ignore_proc_seq_show, -}; - -static int -cio_ignore_proc_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &cio_ignore_proc_seq_ops); -} - -static struct file_operations cio_ignore_proc_fops = { - .open = cio_ignore_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, - .write = cio_ignore_write, -}; - static int cio_ignore_proc_init (void) { @@ -417,7 +340,8 @@ cio_ignore_proc_init (void) if (!entry) return 0; - entry->proc_fops = &cio_ignore_proc_fops; + entry->read_proc = cio_ignore_read; + entry->write_proc = cio_ignore_write; return 1; } diff --git a/trunk/drivers/s390/cio/blacklist.h b/trunk/drivers/s390/cio/blacklist.h index 95e25c1df922..fb42cafbe57c 100644 --- a/trunk/drivers/s390/cio/blacklist.h +++ b/trunk/drivers/s390/cio/blacklist.h @@ -1,6 +1,6 @@ #ifndef S390_BLACKLIST_H #define S390_BLACKLIST_H -extern int is_blacklisted (int ssid, int devno); +extern int is_blacklisted (int devno); #endif diff --git a/trunk/drivers/s390/cio/ccwgroup.c b/trunk/drivers/s390/cio/ccwgroup.c index e849289d4f3c..be9d2d65c22f 100644 --- a/trunk/drivers/s390/cio/ccwgroup.c +++ b/trunk/drivers/s390/cio/ccwgroup.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.33 $ + * $Revision: 1.32 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -263,7 +263,7 @@ ccwgroup_set_online(struct ccwgroup_device *gdev) struct ccwgroup_driver *gdrv; int ret; - if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) + if (atomic_compare_and_swap(0, 1, &gdev->onoff)) return -EAGAIN; if (gdev->state == CCWGROUP_ONLINE) { ret = 0; @@ -289,7 +289,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev) struct ccwgroup_driver *gdrv; int ret; - if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) + if (atomic_compare_and_swap(0, 1, &gdev->onoff)) return -EAGAIN; if (gdev->state == CCWGROUP_OFFLINE) { ret = 0; diff --git a/trunk/drivers/s390/cio/chsc.c b/trunk/drivers/s390/cio/chsc.c index 7270808c02d1..fa3c23b80e3a 100644 --- a/trunk/drivers/s390/cio/chsc.c +++ b/trunk/drivers/s390/cio/chsc.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.126 $ + * $Revision: 1.120 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -24,6 +24,8 @@ #include "ioasm.h" #include "chsc.h" +static struct channel_path *chps[NR_CHPIDS]; + static void *sei_page; static int new_channel_path(int chpid); @@ -31,13 +33,13 @@ static int new_channel_path(int chpid); static inline void set_chp_logically_online(int chp, int onoff) { - css[0]->chps[chp]->state = onoff; + chps[chp]->state = onoff; } static int get_chp_status(int chp) { - return (css[0]->chps[chp] ? css[0]->chps[chp]->state : -ENODEV); + return (chps[chp] ? chps[chp]->state : -ENODEV); } void @@ -75,9 +77,7 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page) struct { struct chsc_header request; - u16 reserved1a:10; - u16 ssid:2; - u16 reserved1b:4; + u16 reserved1; u16 f_sch; /* first subchannel */ u16 reserved2; u16 l_sch; /* last subchannel */ @@ -104,9 +104,8 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page) .code = 0x0004, }; - ssd_area->ssid = sch->schid.ssid; - ssd_area->f_sch = sch->schid.sch_no; - ssd_area->l_sch = sch->schid.sch_no; + ssd_area->f_sch = sch->irq; + ssd_area->l_sch = sch->irq; ccode = chsc(ssd_area); if (ccode > 0) { @@ -148,8 +147,7 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page) */ if (ssd_area->st > 3) { /* uhm, that looks strange... */ CIO_CRW_EVENT(0, "Strange subchannel type %d" - " for sch 0.%x.%04x\n", ssd_area->st, - sch->schid.ssid, sch->schid.sch_no); + " for sch %04x\n", ssd_area->st, sch->irq); /* * There may have been a new subchannel type defined in the * time since this code was written; since we don't know which @@ -158,9 +156,8 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page) return 0; } else { const char *type[4] = {"I/O", "chsc", "message", "ADM"}; - CIO_CRW_EVENT(6, "ssd: sch 0.%x.%04x is %s subchannel\n", - sch->schid.ssid, sch->schid.sch_no, - type[ssd_area->st]); + CIO_CRW_EVENT(6, "ssd: sch %04x is %s subchannel\n", + sch->irq, type[ssd_area->st]); sch->ssd_info.valid = 1; sch->ssd_info.type = ssd_area->st; @@ -221,13 +218,13 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) int j; int mask; struct subchannel *sch; - struct channel_path *chpid; + __u8 *chpid; struct schib schib; sch = to_subchannel(dev); chpid = data; for (j = 0; j < 8; j++) - if (sch->schib.pmcw.chpid[j] == chpid->id) + if (sch->schib.pmcw.chpid[j] == *chpid) break; if (j >= 8) return 0; @@ -235,7 +232,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) mask = 0x80 >> j; spin_lock(&sch->lock); - stsch(sch->schid, &schib); + stsch(sch->irq, &schib); if (!schib.pmcw.dnv) goto out_unreg; memcpy(&sch->schib, &schib, sizeof(struct schib)); @@ -287,7 +284,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) out_unreg: spin_unlock(&sch->lock); sch->lpm = 0; - if (css_enqueue_subchannel_slow(sch->schid)) { + if (css_enqueue_subchannel_slow(sch->irq)) { css_clear_subchannel_slow_list(); need_rescan = 1; } @@ -298,30 +295,23 @@ static inline void s390_set_chpid_offline( __u8 chpid) { char dbf_txt[15]; - struct device *dev; sprintf(dbf_txt, "chpr%x", chpid); CIO_TRACE_EVENT(2, dbf_txt); if (get_chp_status(chpid) <= 0) return; - dev = get_device(&css[0]->chps[chpid]->dev); - bus_for_each_dev(&css_bus_type, NULL, to_channelpath(dev), + + bus_for_each_dev(&css_bus_type, NULL, &chpid, s390_subchannel_remove_chpid); if (need_rescan || css_slow_subchannels_exist()) queue_work(slow_path_wq, &slow_path_work); - put_device(dev); } -struct res_acc_data { - struct channel_path *chp; - u32 fla_mask; - u16 fla; -}; - static int -s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch) +s390_process_res_acc_sch(u8 chpid, __u16 fla, u32 fla_mask, + struct subchannel *sch) { int found; int chp; @@ -333,9 +323,8 @@ s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch) * check if chpid is in information updated by ssd */ if (sch->ssd_info.valid && - sch->ssd_info.chpid[chp] == res_data->chp->id && - (sch->ssd_info.fla[chp] & res_data->fla_mask) - == res_data->fla) { + sch->ssd_info.chpid[chp] == chpid && + (sch->ssd_info.fla[chp] & fla_mask) == fla) { found = 1; break; } @@ -348,87 +337,24 @@ s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch) * new path information and eventually check for logically * offline chpids. */ - ccode = stsch(sch->schid, &sch->schib); + ccode = stsch(sch->irq, &sch->schib); if (ccode > 0) return 0; return 0x80 >> chp; } -static inline int -s390_process_res_acc_new_sch(struct subchannel_id schid) -{ - struct schib schib; - int ret; - /* - * We don't know the device yet, but since a path - * may be available now to the device we'll have - * to do recognition again. - * Since we don't have any idea about which chpid - * that beast may be on we'll have to do a stsch - * on all devices, grr... - */ - if (stsch_err(schid, &schib)) - /* We're through */ - return need_rescan ? -EAGAIN : -ENXIO; - - /* Put it on the slow path. */ - ret = css_enqueue_subchannel_slow(schid); - if (ret) { - css_clear_subchannel_slow_list(); - need_rescan = 1; - return -EAGAIN; - } - return 0; -} - static int -__s390_process_res_acc(struct subchannel_id schid, void *data) +s390_process_res_acc (u8 chpid, __u16 fla, u32 fla_mask) { - int chp_mask, old_lpm; - struct res_acc_data *res_data; struct subchannel *sch; - - res_data = (struct res_acc_data *)data; - sch = get_subchannel_by_schid(schid); - if (!sch) - /* Check if a subchannel is newly available. */ - return s390_process_res_acc_new_sch(schid); - - spin_lock_irq(&sch->lock); - - chp_mask = s390_process_res_acc_sch(res_data, sch); - - if (chp_mask == 0) { - spin_unlock_irq(&sch->lock); - return 0; - } - old_lpm = sch->lpm; - sch->lpm = ((sch->schib.pmcw.pim & - sch->schib.pmcw.pam & - sch->schib.pmcw.pom) - | chp_mask) & sch->opm; - if (!old_lpm && sch->lpm) - device_trigger_reprobe(sch); - else if (sch->driver && sch->driver->verify) - sch->driver->verify(&sch->dev); - - spin_unlock_irq(&sch->lock); - put_device(&sch->dev); - return (res_data->fla_mask == 0xffff) ? -ENODEV : 0; -} - - -static int -s390_process_res_acc (struct res_acc_data *res_data) -{ - int rc; + int irq, rc; char dbf_txt[15]; - sprintf(dbf_txt, "accpr%x", res_data->chp->id); + sprintf(dbf_txt, "accpr%x", chpid); CIO_TRACE_EVENT( 2, dbf_txt); - if (res_data->fla != 0) { - sprintf(dbf_txt, "fla%x", res_data->fla); + if (fla != 0) { + sprintf(dbf_txt, "fla%x", fla); CIO_TRACE_EVENT( 2, dbf_txt); } @@ -439,11 +365,70 @@ s390_process_res_acc (struct res_acc_data *res_data) * The more information we have (info), the less scanning * will we have to do. */ - rc = for_each_subchannel(__s390_process_res_acc, res_data); - if (css_slow_subchannels_exist()) - rc = -EAGAIN; - else if (rc != -EAGAIN) - rc = 0; + + if (!get_chp_status(chpid)) + return 0; /* no need to do the rest */ + + rc = 0; + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { + int chp_mask, old_lpm; + + sch = get_subchannel_by_schid(irq); + if (!sch) { + struct schib schib; + int ret; + /* + * We don't know the device yet, but since a path + * may be available now to the device we'll have + * to do recognition again. + * Since we don't have any idea about which chpid + * that beast may be on we'll have to do a stsch + * on all devices, grr... + */ + if (stsch(irq, &schib)) { + /* We're through */ + if (need_rescan) + rc = -EAGAIN; + break; + } + if (need_rescan) { + rc = -EAGAIN; + continue; + } + /* Put it on the slow path. */ + ret = css_enqueue_subchannel_slow(irq); + if (ret) { + css_clear_subchannel_slow_list(); + need_rescan = 1; + } + rc = -EAGAIN; + continue; + } + + spin_lock_irq(&sch->lock); + + chp_mask = s390_process_res_acc_sch(chpid, fla, fla_mask, sch); + + if (chp_mask == 0) { + + spin_unlock_irq(&sch->lock); + continue; + } + old_lpm = sch->lpm; + sch->lpm = ((sch->schib.pmcw.pim & + sch->schib.pmcw.pam & + sch->schib.pmcw.pom) + | chp_mask) & sch->opm; + if (!old_lpm && sch->lpm) + device_trigger_reprobe(sch); + else if (sch->driver && sch->driver->verify) + sch->driver->verify(&sch->dev); + + spin_unlock_irq(&sch->lock); + put_device(&sch->dev); + if (fla_mask == 0xffff) + break; + } return rc; } @@ -481,7 +466,6 @@ int chsc_process_crw(void) { int chpid, ret; - struct res_acc_data res_data; struct { struct chsc_header request; u32 reserved1; @@ -515,9 +499,8 @@ chsc_process_crw(void) ret = 0; do { int ccode, status; - struct device *dev; memset(sei_area, 0, sizeof(*sei_area)); - memset(&res_data, 0, sizeof(struct res_acc_data)); + sei_area->request = (struct chsc_header) { .length = 0x0010, .code = 0x000e, @@ -590,25 +573,26 @@ chsc_process_crw(void) if (status < 0) new_channel_path(sei_area->rsid); else if (!status) - break; - dev = get_device(&css[0]->chps[sei_area->rsid]->dev); - res_data.chp = to_channelpath(dev); - pr_debug("chpid: %x", sei_area->rsid); - if ((sei_area->vf & 0xc0) != 0) { - res_data.fla = sei_area->fla; - if ((sei_area->vf & 0xc0) == 0xc0) { - pr_debug(" full link addr: %x", - sei_area->fla); - res_data.fla_mask = 0xffff; - } else { - pr_debug(" link addr: %x", - sei_area->fla); - res_data.fla_mask = 0xff00; - } + return 0; + if ((sei_area->vf & 0x80) == 0) { + pr_debug("chpid: %x\n", sei_area->rsid); + ret = s390_process_res_acc(sei_area->rsid, + 0, 0); + } else if ((sei_area->vf & 0xc0) == 0x80) { + pr_debug("chpid: %x link addr: %x\n", + sei_area->rsid, sei_area->fla); + ret = s390_process_res_acc(sei_area->rsid, + sei_area->fla, + 0xff00); + } else if ((sei_area->vf & 0xc0) == 0xc0) { + pr_debug("chpid: %x full link addr: %x\n", + sei_area->rsid, sei_area->fla); + ret = s390_process_res_acc(sei_area->rsid, + sei_area->fla, + 0xffff); } - ret = s390_process_res_acc(&res_data); - pr_debug("\n\n"); - put_device(dev); + pr_debug("\n"); + break; default: /* other stuff */ @@ -620,72 +604,12 @@ chsc_process_crw(void) return ret; } -static inline int -__chp_add_new_sch(struct subchannel_id schid) -{ - struct schib schib; - int ret; - - if (stsch(schid, &schib)) - /* We're through */ - return need_rescan ? -EAGAIN : -ENXIO; - - /* Put it on the slow path. */ - ret = css_enqueue_subchannel_slow(schid); - if (ret) { - css_clear_subchannel_slow_list(); - need_rescan = 1; - return -EAGAIN; - } - return 0; -} - - -static int -__chp_add(struct subchannel_id schid, void *data) -{ - int i; - struct channel_path *chp; - struct subchannel *sch; - - chp = (struct channel_path *)data; - sch = get_subchannel_by_schid(schid); - if (!sch) - /* Check if the subchannel is now available. */ - return __chp_add_new_sch(schid); - spin_lock(&sch->lock); - for (i=0; i<8; i++) - if (sch->schib.pmcw.chpid[i] == chp->id) { - if (stsch(sch->schid, &sch->schib) != 0) { - /* Endgame. */ - spin_unlock(&sch->lock); - return -ENXIO; - } - break; - } - if (i==8) { - spin_unlock(&sch->lock); - return 0; - } - sch->lpm = ((sch->schib.pmcw.pim & - sch->schib.pmcw.pam & - sch->schib.pmcw.pom) - | 0x80 >> i) & sch->opm; - - if (sch->driver && sch->driver->verify) - sch->driver->verify(&sch->dev); - - spin_unlock(&sch->lock); - put_device(&sch->dev); - return 0; -} - static int chp_add(int chpid) { - int rc; + struct subchannel *sch; + int irq, ret, rc; char dbf_txt[15]; - struct device *dev; if (!get_chp_status(chpid)) return 0; /* no need to do the rest */ @@ -693,13 +617,59 @@ chp_add(int chpid) sprintf(dbf_txt, "cadd%x", chpid); CIO_TRACE_EVENT(2, dbf_txt); - dev = get_device(&css[0]->chps[chpid]->dev); - rc = for_each_subchannel(__chp_add, to_channelpath(dev)); - if (css_slow_subchannels_exist()) - rc = -EAGAIN; - if (rc != -EAGAIN) - rc = 0; - put_device(dev); + rc = 0; + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { + int i; + + sch = get_subchannel_by_schid(irq); + if (!sch) { + struct schib schib; + + if (stsch(irq, &schib)) { + /* We're through */ + if (need_rescan) + rc = -EAGAIN; + break; + } + if (need_rescan) { + rc = -EAGAIN; + continue; + } + /* Put it on the slow path. */ + ret = css_enqueue_subchannel_slow(irq); + if (ret) { + css_clear_subchannel_slow_list(); + need_rescan = 1; + } + rc = -EAGAIN; + continue; + } + + spin_lock(&sch->lock); + for (i=0; i<8; i++) + if (sch->schib.pmcw.chpid[i] == chpid) { + if (stsch(sch->irq, &sch->schib) != 0) { + /* Endgame. */ + spin_unlock(&sch->lock); + return rc; + } + break; + } + if (i==8) { + spin_unlock(&sch->lock); + return rc; + } + sch->lpm = ((sch->schib.pmcw.pim & + sch->schib.pmcw.pam & + sch->schib.pmcw.pom) + | 0x80 >> i) & sch->opm; + + if (sch->driver && sch->driver->verify) + sch->driver->verify(&sch->dev); + + spin_unlock(&sch->lock); + put_device(&sch->dev); + } return rc; } @@ -732,7 +702,7 @@ __check_for_io_and_kill(struct subchannel *sch, int index) if (!device_is_online(sch)) /* cio could be doing I/O. */ return 0; - cc = stsch(sch->schid, &sch->schib); + cc = stsch(sch->irq, &sch->schib); if (cc) return 0; if (sch->schib.scsw.actl && sch->schib.pmcw.lpum == (0x80 >> index)) { @@ -773,7 +743,7 @@ __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) * just varied off path. Then kill it. */ if (!__check_for_io_and_kill(sch, chp) && !sch->lpm) { - if (css_enqueue_subchannel_slow(sch->schid)) { + if (css_enqueue_subchannel_slow(sch->irq)) { css_clear_subchannel_slow_list(); need_rescan = 1; } @@ -811,29 +781,6 @@ s390_subchannel_vary_chpid_on(struct device *dev, void *data) return 0; } -static int -__s390_vary_chpid_on(struct subchannel_id schid, void *data) -{ - struct schib schib; - struct subchannel *sch; - - sch = get_subchannel_by_schid(schid); - if (sch) { - put_device(&sch->dev); - return 0; - } - if (stsch_err(schid, &schib)) - /* We're through */ - return -ENXIO; - /* Put it on the slow path. */ - if (css_enqueue_subchannel_slow(schid)) { - css_clear_subchannel_slow_list(); - need_rescan = 1; - return -EAGAIN; - } - return 0; -} - /* * Function: s390_vary_chpid * Varies the specified chpid online or offline @@ -842,7 +789,8 @@ static int s390_vary_chpid( __u8 chpid, int on) { char dbf_text[15]; - int status; + int status, irq, ret; + struct subchannel *sch; sprintf(dbf_text, on?"varyon%x":"varyoff%x", chpid); CIO_TRACE_EVENT( 2, dbf_text); @@ -867,9 +815,30 @@ s390_vary_chpid( __u8 chpid, int on) bus_for_each_dev(&css_bus_type, NULL, &chpid, on ? s390_subchannel_vary_chpid_on : s390_subchannel_vary_chpid_off); - if (on) - /* Scan for new devices on varied on path. */ - for_each_subchannel(__s390_vary_chpid_on, NULL); + if (!on) + goto out; + /* Scan for new devices on varied on path. */ + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { + struct schib schib; + + if (need_rescan) + break; + sch = get_subchannel_by_schid(irq); + if (sch) { + put_device(&sch->dev); + continue; + } + if (stsch(irq, &schib)) + /* We're through */ + break; + /* Put it on the slow path. */ + ret = css_enqueue_subchannel_slow(irq); + if (ret) { + css_clear_subchannel_slow_list(); + need_rescan = 1; + } + } +out: if (need_rescan || css_slow_subchannels_exist()) queue_work(slow_path_wq, &slow_path_work); return 0; @@ -1026,7 +995,7 @@ new_channel_path(int chpid) chp->id = chpid; chp->state = 1; chp->dev = (struct device) { - .parent = &css[0]->device, + .parent = &css_bus_device, .release = chp_release, }; snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid); @@ -1048,7 +1017,7 @@ new_channel_path(int chpid) device_unregister(&chp->dev); goto out_free; } else - css[0]->chps[chpid] = chp; + chps[chpid] = chp; return ret; out_free: kfree(chp); @@ -1061,7 +1030,7 @@ chsc_get_chp_desc(struct subchannel *sch, int chp_no) struct channel_path *chp; struct channel_path_desc *desc; - chp = css[0]->chps[sch->schib.pmcw.chpid[chp_no]]; + chp = chps[sch->schib.pmcw.chpid[chp_no]]; if (!chp) return NULL; desc = kmalloc(sizeof(struct channel_path_desc), GFP_KERNEL); @@ -1082,54 +1051,6 @@ chsc_alloc_sei_area(void) return (sei_page ? 0 : -ENOMEM); } -int __init -chsc_enable_facility(int operation_code) -{ - int ret; - struct { - struct chsc_header request; - u8 reserved1:4; - u8 format:4; - u8 reserved2; - u16 operation_code; - u32 reserved3; - u32 reserved4; - u32 operation_data_area[252]; - struct chsc_header response; - u32 reserved5:4; - u32 format2:4; - u32 reserved6:24; - } *sda_area; - - sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); - if (!sda_area) - return -ENOMEM; - sda_area->request = (struct chsc_header) { - .length = 0x0400, - .code = 0x0031, - }; - sda_area->operation_code = operation_code; - - ret = chsc(sda_area); - if (ret > 0) { - ret = (ret == 3) ? -ENODEV : -EBUSY; - goto out; - } - switch (sda_area->response.code) { - case 0x0003: /* invalid request block */ - case 0x0007: - ret = -EINVAL; - break; - case 0x0004: /* command not provided */ - case 0x0101: /* facility not provided */ - ret = -EOPNOTSUPP; - break; - } - out: - free_page((unsigned long)sda_area); - return ret; -} - subsys_initcall(chsc_alloc_sei_area); struct css_general_char css_general_characteristics; diff --git a/trunk/drivers/s390/cio/chsc.h b/trunk/drivers/s390/cio/chsc.h index 44e4b4bb1c5a..be20da49d147 100644 --- a/trunk/drivers/s390/cio/chsc.h +++ b/trunk/drivers/s390/cio/chsc.h @@ -1,12 +1,12 @@ #ifndef S390_CHSC_H #define S390_CHSC_H +#define NR_CHPIDS 256 + #define CHSC_SEI_ACC_CHPID 1 #define CHSC_SEI_ACC_LINKADDR 2 #define CHSC_SEI_ACC_FULLLINKADDR 3 -#define CHSC_SDA_OC_MSS 0x2 - struct chsc_header { u16 length; u16 code; @@ -43,9 +43,7 @@ struct css_general_char { u32 ext_mb : 1; /* bit 48 */ u32 : 7; u32 aif_tdd : 1; /* bit 56 */ - u32 : 1; - u32 qebsm : 1; /* bit 58 */ - u32 : 8; + u32 : 10; u32 aif_osa : 1; /* bit 67 */ u32 : 28; }__attribute__((packed)); @@ -65,9 +63,4 @@ extern int chsc_determine_css_characteristics(void); extern int css_characteristics_avail; extern void *chsc_get_chp_desc(struct subchannel*, int); - -extern int chsc_enable_facility(int); - -#define to_channelpath(dev) container_of(dev, struct channel_path, dev) - #endif diff --git a/trunk/drivers/s390/cio/cio.c b/trunk/drivers/s390/cio/cio.c index 7376bc87206d..185bc73c3ecd 100644 --- a/trunk/drivers/s390/cio/cio.c +++ b/trunk/drivers/s390/cio/cio.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/cio.c * S/390 common I/O routines -- low level i/o calls - * $Revision: 1.138 $ + * $Revision: 1.135 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -135,7 +135,7 @@ cio_tpi(void) return 0; irb = (struct irb *) __LC_IRB; /* Store interrupt response block to lowcore. */ - if (tsch (tpi_info->schid, irb) != 0) + if (tsch (tpi_info->irq, irb) != 0) /* Not status pending or not operational. */ return 1; sch = (struct subchannel *)(unsigned long)tpi_info->intparm; @@ -163,11 +163,10 @@ cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) else sch->lpm = 0; - stsch (sch->schid, &sch->schib); + stsch (sch->irq, &sch->schib); CIO_MSG_EVENT(0, "cio_start: 'not oper' status for " - "subchannel 0.%x.%04x!\n", sch->schid.ssid, - sch->schid.sch_no); + "subchannel %04x!\n", sch->irq); sprintf(dbf_text, "no%s", sch->dev.bus_id); CIO_TRACE_EVENT(0, dbf_text); CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); @@ -195,7 +194,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ sch->orb.spnd = sch->options.suspend; sch->orb.ssic = sch->options.suspend && sch->options.inter; sch->orb.lpm = (lpm != 0) ? (lpm & sch->opm) : sch->lpm; -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X /* * for 64 bit we always support 64 bit IDAWs with 4k page size only */ @@ -205,7 +204,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ sch->orb.key = key >> 4; /* issue "Start Subchannel" */ sch->orb.cpa = (__u32) __pa (cpa); - ccode = ssch (sch->schid, &sch->orb); + ccode = ssch (sch->irq, &sch->orb); /* process condition code */ sprintf (dbf_txt, "ccode:%d", ccode); @@ -244,7 +243,7 @@ cio_resume (struct subchannel *sch) CIO_TRACE_EVENT (4, "resIO"); CIO_TRACE_EVENT (4, sch->dev.bus_id); - ccode = rsch (sch->schid); + ccode = rsch (sch->irq); sprintf (dbf_txt, "ccode:%d", ccode); CIO_TRACE_EVENT (4, dbf_txt); @@ -284,7 +283,7 @@ cio_halt(struct subchannel *sch) /* * Issue "Halt subchannel" and process condition code */ - ccode = hsch (sch->schid); + ccode = hsch (sch->irq); sprintf (dbf_txt, "ccode:%d", ccode); CIO_TRACE_EVENT (2, dbf_txt); @@ -319,7 +318,7 @@ cio_clear(struct subchannel *sch) /* * Issue "Clear subchannel" and process condition code */ - ccode = csch (sch->schid); + ccode = csch (sch->irq); sprintf (dbf_txt, "ccode:%d", ccode); CIO_TRACE_EVENT (2, dbf_txt); @@ -352,7 +351,7 @@ cio_cancel (struct subchannel *sch) CIO_TRACE_EVENT (2, "cancelIO"); CIO_TRACE_EVENT (2, sch->dev.bus_id); - ccode = xsch (sch->schid); + ccode = xsch (sch->irq); sprintf (dbf_txt, "ccode:%d", ccode); CIO_TRACE_EVENT (2, dbf_txt); @@ -360,7 +359,7 @@ cio_cancel (struct subchannel *sch) switch (ccode) { case 0: /* success */ /* Update information in scsw. */ - stsch (sch->schid, &sch->schib); + stsch (sch->irq, &sch->schib); return 0; case 1: /* status pending */ return -EBUSY; @@ -382,7 +381,7 @@ cio_modify (struct subchannel *sch) ret = 0; for (retry = 0; retry < 5; retry++) { - ccode = msch_err (sch->schid, &sch->schib); + ccode = msch_err (sch->irq, &sch->schib); if (ccode < 0) /* -EIO if msch gets a program check. */ return ccode; switch (ccode) { @@ -415,7 +414,7 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc) CIO_TRACE_EVENT (2, "ensch"); CIO_TRACE_EVENT (2, sch->dev.bus_id); - ccode = stsch (sch->schid, &sch->schib); + ccode = stsch (sch->irq, &sch->schib); if (ccode) return -ENODEV; @@ -433,13 +432,13 @@ cio_enable_subchannel (struct subchannel *sch, unsigned int isc) */ sch->schib.pmcw.csense = 0; if (ret == 0) { - stsch (sch->schid, &sch->schib); + stsch (sch->irq, &sch->schib); if (sch->schib.pmcw.ena) break; } if (ret == -EBUSY) { struct irb irb; - if (tsch(sch->schid, &irb) != 0) + if (tsch(sch->irq, &irb) != 0) break; } } @@ -462,7 +461,7 @@ cio_disable_subchannel (struct subchannel *sch) CIO_TRACE_EVENT (2, "dissch"); CIO_TRACE_EVENT (2, sch->dev.bus_id); - ccode = stsch (sch->schid, &sch->schib); + ccode = stsch (sch->irq, &sch->schib); if (ccode == 3) /* Not operational. */ return -ENODEV; @@ -486,7 +485,7 @@ cio_disable_subchannel (struct subchannel *sch) */ break; if (ret == 0) { - stsch (sch->schid, &sch->schib); + stsch (sch->irq, &sch->schib); if (!sch->schib.pmcw.ena) break; } @@ -509,12 +508,12 @@ cio_disable_subchannel (struct subchannel *sch) * -ENODEV for subchannels with invalid device number or blacklisted devices */ int -cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) +cio_validate_subchannel (struct subchannel *sch, unsigned int irq) { char dbf_txt[15]; int ccode; - sprintf (dbf_txt, "valsch%x", schid.sch_no); + sprintf (dbf_txt, "valsch%x", irq); CIO_TRACE_EVENT (4, dbf_txt); /* Nuke all fields. */ @@ -523,20 +522,17 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) spin_lock_init(&sch->lock); /* Set a name for the subchannel */ - snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", schid.ssid, - schid.sch_no); + snprintf (sch->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", irq); /* * The first subchannel that is not-operational (ccode==3) * indicates that there aren't any more devices available. - * If stsch gets an exception, it means the current subchannel set - * is not valid. */ - ccode = stsch_err (schid, &sch->schib); + sch->irq = irq; + ccode = stsch (irq, &sch->schib); if (ccode) - return (ccode == 3) ? -ENXIO : ccode; + return -ENXIO; - sch->schid = schid; /* Copy subchannel type from path management control word. */ sch->st = sch->schib.pmcw.st; @@ -545,9 +541,9 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) */ if (sch->st != 0) { CIO_DEBUG(KERN_INFO, 0, - "Subchannel 0.%x.%04x reports " + "Subchannel %04X reports " "non-I/O subchannel type %04X\n", - sch->schid.ssid, sch->schid.sch_no, sch->st); + sch->irq, sch->st); /* We stop here for non-io subchannels. */ return sch->st; } @@ -558,29 +554,26 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) return -ENODEV; /* Devno is valid. */ - if (is_blacklisted (sch->schid.ssid, sch->schib.pmcw.dev)) { + if (is_blacklisted (sch->schib.pmcw.dev)) { /* * This device must not be known to Linux. So we simply * say that there is no device and return ENODEV. */ CIO_MSG_EVENT(0, "Blacklisted device detected " - "at devno %04X, subchannel set %x\n", - sch->schib.pmcw.dev, sch->schid.ssid); + "at devno %04X\n", sch->schib.pmcw.dev); return -ENODEV; } sch->opm = 0xff; - if (!cio_is_console(sch->schid)) - chsc_validate_chpids(sch); + chsc_validate_chpids(sch); sch->lpm = sch->schib.pmcw.pim & sch->schib.pmcw.pam & sch->schib.pmcw.pom & sch->opm; CIO_DEBUG(KERN_INFO, 0, - "Detected device %04x on subchannel 0.%x.%04X" + "Detected device %04X on subchannel %04X" " - PIM = %02X, PAM = %02X, POM = %02X\n", - sch->schib.pmcw.dev, sch->schid.ssid, - sch->schid.sch_no, sch->schib.pmcw.pim, + sch->schib.pmcw.dev, sch->irq, sch->schib.pmcw.pim, sch->schib.pmcw.pam, sch->schib.pmcw.pom); /* @@ -639,7 +632,7 @@ do_IRQ (struct pt_regs *regs) if (sch) spin_lock(&sch->lock); /* Store interrupt response block to lowcore. */ - if (tsch (tpi_info->schid, irb) == 0 && sch) { + if (tsch (tpi_info->irq, irb) == 0 && sch) { /* Keep subchannel information word up to date. */ memcpy (&sch->schib.scsw, &irb->scsw, sizeof (irb->scsw)); @@ -698,36 +691,28 @@ wait_cons_dev (void) } static int -cio_test_for_console(struct subchannel_id schid, void *data) +cio_console_irq(void) { - if (stsch_err(schid, &console_subchannel.schib) != 0) - return -ENXIO; - if (console_subchannel.schib.pmcw.dnv && - console_subchannel.schib.pmcw.dev == - console_devno) { - console_irq = schid.sch_no; - return 1; /* found */ - } - return 0; -} - - -static int -cio_get_console_sch_no(void) -{ - struct subchannel_id schid; + int irq; - init_subchannel_id(&schid); if (console_irq != -1) { /* VM provided us with the irq number of the console. */ - schid.sch_no = console_irq; - if (stsch(schid, &console_subchannel.schib) != 0 || + if (stsch(console_irq, &console_subchannel.schib) != 0 || !console_subchannel.schib.pmcw.dnv) return -1; console_devno = console_subchannel.schib.pmcw.dev; } else if (console_devno != -1) { /* At least the console device number is known. */ - for_each_subchannel(cio_test_for_console, NULL); + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { + if (stsch(irq, &console_subchannel.schib) != 0) + break; + if (console_subchannel.schib.pmcw.dnv && + console_subchannel.schib.pmcw.dev == + console_devno) { + console_irq = irq; + break; + } + } if (console_irq == -1) return -1; } else { @@ -743,20 +728,17 @@ cio_get_console_sch_no(void) struct subchannel * cio_probe_console(void) { - int sch_no, ret; - struct subchannel_id schid; + int irq, ret; if (xchg(&console_subchannel_in_use, 1) != 0) return ERR_PTR(-EBUSY); - sch_no = cio_get_console_sch_no(); - if (sch_no == -1) { + irq = cio_console_irq(); + if (irq == -1) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); } memset(&console_subchannel, 0, sizeof(struct subchannel)); - init_subchannel_id(&schid); - schid.sch_no = sch_no; - ret = cio_validate_subchannel(&console_subchannel, schid); + ret = cio_validate_subchannel(&console_subchannel, irq); if (ret) { console_subchannel_in_use = 0; return ERR_PTR(-ENODEV); @@ -788,11 +770,11 @@ cio_release_console(void) /* Bah... hack to catch console special sausages. */ int -cio_is_console(struct subchannel_id schid) +cio_is_console(int irq) { if (!console_subchannel_in_use) return 0; - return schid_equal(&schid, &console_subchannel.schid); + return (irq == console_subchannel.irq); } struct subchannel * @@ -805,7 +787,7 @@ cio_get_console_subchannel(void) #endif static inline int -__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) +__disable_subchannel_easy(unsigned int schid, struct schib *schib) { int retry, cc; @@ -823,7 +805,7 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) } static inline int -__clear_subchannel_easy(struct subchannel_id schid) +__clear_subchannel_easy(unsigned int schid) { int retry; @@ -833,8 +815,8 @@ __clear_subchannel_easy(struct subchannel_id schid) struct tpi_info ti; if (tpi(&ti)) { - tsch(ti.schid, (struct irb *)__LC_IRB); - if (schid_equal(&ti.schid, &schid)) + tsch(ti.irq, (struct irb *)__LC_IRB); + if (ti.irq == schid) return 0; } udelay(100); @@ -843,33 +825,31 @@ __clear_subchannel_easy(struct subchannel_id schid) } extern void do_reipl(unsigned long devno); -static int -__shutdown_subchannel_easy(struct subchannel_id schid, void *data) -{ - struct schib schib; - - if (stsch_err(schid, &schib)) - return -ENXIO; - if (!schib.pmcw.ena) - return 0; - switch(__disable_subchannel_easy(schid, &schib)) { - case 0: - case -ENODEV: - break; - default: /* -EBUSY */ - if (__clear_subchannel_easy(schid)) - break; /* give up... */ - stsch(schid, &schib); - __disable_subchannel_easy(schid, &schib); - } - return 0; -} +/* Clear all subchannels. */ void clear_all_subchannels(void) { + unsigned int schid; + local_irq_disable(); - for_each_subchannel(__shutdown_subchannel_easy, NULL); + for (schid=0;schid<=highest_subchannel;schid++) { + struct schib schib; + if (stsch(schid, &schib)) + break; /* break out of the loop */ + if (!schib.pmcw.ena) + continue; + switch(__disable_subchannel_easy(schid, &schib)) { + case 0: + case -ENODEV: + break; + default: /* -EBUSY */ + if (__clear_subchannel_easy(schid)) + break; /* give up... jump out of switch */ + stsch(schid, &schib); + __disable_subchannel_easy(schid, &schib); + } + } } /* Make sure all subchannels are quiet before we re-ipl an lpar. */ diff --git a/trunk/drivers/s390/cio/cio.h b/trunk/drivers/s390/cio/cio.h index 0ca987344e07..c50a9da420a9 100644 --- a/trunk/drivers/s390/cio/cio.h +++ b/trunk/drivers/s390/cio/cio.h @@ -1,8 +1,6 @@ #ifndef S390_CIO_H #define S390_CIO_H -#include "schid.h" - /* * where we put the ssd info */ @@ -85,7 +83,7 @@ struct orb { /* subchannel data structure used by I/O subroutines */ struct subchannel { - struct subchannel_id schid; + unsigned int irq; /* aka. subchannel number */ spinlock_t lock; /* subchannel lock */ enum { @@ -116,7 +114,7 @@ struct subchannel { #define to_subchannel(n) container_of(n, struct subchannel, dev) -extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id); +extern int cio_validate_subchannel (struct subchannel *, unsigned int); extern int cio_enable_subchannel (struct subchannel *, unsigned int); extern int cio_disable_subchannel (struct subchannel *); extern int cio_cancel (struct subchannel *); @@ -129,15 +127,14 @@ extern int cio_cancel (struct subchannel *); extern int cio_set_options (struct subchannel *, int); extern int cio_get_options (struct subchannel *); extern int cio_modify (struct subchannel *); - /* Use with care. */ #ifdef CONFIG_CCW_CONSOLE extern struct subchannel *cio_probe_console(void); extern void cio_release_console(void); -extern int cio_is_console(struct subchannel_id); +extern int cio_is_console(int irq); extern struct subchannel *cio_get_console_subchannel(void); #else -#define cio_is_console(schid) 0 +#define cio_is_console(irq) 0 #define cio_get_console_subchannel() NULL #endif diff --git a/trunk/drivers/s390/cio/cmf.c b/trunk/drivers/s390/cio/cmf.c index 0b03714e696a..b978f7fe8327 100644 --- a/trunk/drivers/s390/cio/cmf.c +++ b/trunk/drivers/s390/cio/cmf.c @@ -1,5 +1,5 @@ /* - * linux/drivers/s390/cio/cmf.c ($Revision: 1.19 $) + * linux/drivers/s390/cio/cmf.c ($Revision: 1.16 $) * * Linux on zSeries Channel Measurement Facility support * @@ -178,7 +178,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address) /* msch can silently fail, so do it again if necessary */ for (retry = 0; retry < 3; retry++) { /* prepare schib */ - stsch(sch->schid, schib); + stsch(sch->irq, schib); schib->pmcw.mme = mme; schib->pmcw.mbfc = mbfc; /* address can be either a block address or a block index */ @@ -188,7 +188,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address) schib->pmcw.mbi = address; /* try to submit it */ - switch(ret = msch_err(sch->schid, schib)) { + switch(ret = msch_err(sch->irq, schib)) { case 0: break; case 1: @@ -202,7 +202,7 @@ set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address) ret = -EINVAL; break; } - stsch(sch->schid, schib); /* restore the schib */ + stsch(sch->irq, schib); /* restore the schib */ if (ret) break; diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index e565193650c7..555119cacc27 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/css.c * driver for channel subsystem - * $Revision: 1.93 $ + * $Revision: 1.85 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -21,35 +21,19 @@ #include "ioasm.h" #include "chsc.h" +unsigned int highest_subchannel; int need_rescan = 0; int css_init_done = 0; -static int max_ssid = 0; - -struct channel_subsystem *css[__MAX_CSSID + 1]; +struct pgid global_pgid; int css_characteristics_avail = 0; -inline int -for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) -{ - struct subchannel_id schid; - int ret; - - init_subchannel_id(&schid); - ret = -ENODEV; - do { - do { - ret = fn(schid, data); - if (ret) - break; - } while (schid.sch_no++ < __MAX_SUBCHANNEL); - schid.sch_no = 0; - } while (schid.ssid++ < max_ssid); - return ret; -} +struct device css_bus_device = { + .bus_id = "css0", +}; static struct subchannel * -css_alloc_subchannel(struct subchannel_id schid) +css_alloc_subchannel(int irq) { struct subchannel *sch; int ret; @@ -57,11 +41,13 @@ css_alloc_subchannel(struct subchannel_id schid) sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA); if (sch == NULL) return ERR_PTR(-ENOMEM); - ret = cio_validate_subchannel (sch, schid); + ret = cio_validate_subchannel (sch, irq); if (ret < 0) { kfree(sch); return ERR_PTR(ret); } + if (irq > highest_subchannel) + highest_subchannel = irq; if (sch->st != SUBCHANNEL_TYPE_IO) { /* For now we ignore all non-io subchannels. */ @@ -101,7 +87,7 @@ css_subchannel_release(struct device *dev) struct subchannel *sch; sch = to_subchannel(dev); - if (!cio_is_console(sch->schid)) + if (!cio_is_console(sch->irq)) kfree(sch); } @@ -113,7 +99,7 @@ css_register_subchannel(struct subchannel *sch) int ret; /* Initialize the subchannel structure */ - sch->dev.parent = &css[0]->device; + sch->dev.parent = &css_bus_device; sch->dev.bus = &css_bus_type; sch->dev.release = &css_subchannel_release; @@ -128,12 +114,12 @@ css_register_subchannel(struct subchannel *sch) } int -css_probe_device(struct subchannel_id schid) +css_probe_device(int irq) { int ret; struct subchannel *sch; - sch = css_alloc_subchannel(schid); + sch = css_alloc_subchannel(irq); if (IS_ERR(sch)) return PTR_ERR(sch); ret = css_register_subchannel(sch); @@ -146,26 +132,26 @@ static int check_subchannel(struct device * dev, void * data) { struct subchannel *sch; - struct subchannel_id *schid = data; + int irq = (unsigned long)data; sch = to_subchannel(dev); - return schid_equal(&sch->schid, schid); + return (sch->irq == irq); } struct subchannel * -get_subchannel_by_schid(struct subchannel_id schid) +get_subchannel_by_schid(int irq) { struct device *dev; dev = bus_find_device(&css_bus_type, NULL, - (void *)&schid, check_subchannel); + (void *)(unsigned long)irq, check_subchannel); return dev ? to_subchannel(dev) : NULL; } static inline int -css_get_subchannel_status(struct subchannel *sch, struct subchannel_id schid) +css_get_subchannel_status(struct subchannel *sch, int schid) { struct schib schib; int cc; @@ -184,13 +170,13 @@ css_get_subchannel_status(struct subchannel *sch, struct subchannel_id schid) } static int -css_evaluate_subchannel(struct subchannel_id schid, int slow) +css_evaluate_subchannel(int irq, int slow) { int event, ret, disc; struct subchannel *sch; unsigned long flags; - sch = get_subchannel_by_schid(schid); + sch = get_subchannel_by_schid(irq); disc = sch ? device_is_disconnected(sch) : 0; if (disc && slow) { if (sch) @@ -208,10 +194,9 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow) put_device(&sch->dev); return -EAGAIN; /* Will be done on the slow path. */ } - event = css_get_subchannel_status(sch, schid); - CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n", - schid.ssid, schid.sch_no, event, - sch?(disc?"disconnected":"normal"):"unknown", + event = css_get_subchannel_status(sch, irq); + CIO_MSG_EVENT(4, "Evaluating schid %04x, event %d, %s, %s path.\n", + irq, event, sch?(disc?"disconnected":"normal"):"unknown", slow?"slow":"fast"); switch (event) { case CIO_NO_PATH: @@ -268,7 +253,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow) sch->schib.pmcw.intparm = 0; cio_modify(sch); put_device(&sch->dev); - ret = css_probe_device(schid); + ret = css_probe_device(irq); } else { /* * We can't immediately deregister the disconnected @@ -287,7 +272,7 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow) device_trigger_reprobe(sch); spin_unlock_irqrestore(&sch->lock, flags); } - ret = sch ? 0 : css_probe_device(schid); + ret = sch ? 0 : css_probe_device(irq); break; default: BUG(); @@ -296,15 +281,28 @@ css_evaluate_subchannel(struct subchannel_id schid, int slow) return ret; } -static int -css_rescan_devices(struct subchannel_id schid, void *data) +static void +css_rescan_devices(void) { - return css_evaluate_subchannel(schid, 1); + int irq, ret; + + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { + ret = css_evaluate_subchannel(irq, 1); + /* No more memory. It doesn't make sense to continue. No + * panic because this can happen in midflight and just + * because we can't use a new device is no reason to crash + * the system. */ + if (ret == -ENOMEM) + break; + /* -ENXIO indicates that there are no more subchannels. */ + if (ret == -ENXIO) + break; + } } struct slow_subchannel { struct list_head slow_list; - struct subchannel_id schid; + unsigned long schid; }; static LIST_HEAD(slow_subchannels_head); @@ -317,7 +315,7 @@ css_trigger_slow_path(void) if (need_rescan) { need_rescan = 0; - for_each_subchannel(css_rescan_devices, NULL); + css_rescan_devices(); return; } @@ -356,31 +354,23 @@ css_reiterate_subchannels(void) * Called from the machine check handler for subchannel report words. */ int -css_process_crw(int rsid1, int rsid2) +css_process_crw(int irq) { int ret; - struct subchannel_id mchk_schid; - CIO_CRW_EVENT(2, "source is subchannel %04X, subsystem id %x\n", - rsid1, rsid2); + CIO_CRW_EVENT(2, "source is subchannel %04X\n", irq); if (need_rescan) /* We need to iterate all subchannels anyway. */ return -EAGAIN; - - init_subchannel_id(&mchk_schid); - mchk_schid.sch_no = rsid1; - if (rsid2 != 0) - mchk_schid.ssid = (rsid2 >> 8) & 3; - /* * Since we are always presented with IPI in the CRW, we have to * use stsch() to find out if the subchannel in question has come * or gone. */ - ret = css_evaluate_subchannel(mchk_schid, 0); + ret = css_evaluate_subchannel(irq, 0); if (ret == -EAGAIN) { - if (css_enqueue_subchannel_slow(mchk_schid)) { + if (css_enqueue_subchannel_slow(irq)) { css_clear_subchannel_slow_list(); need_rescan = 1; } @@ -388,83 +378,22 @@ css_process_crw(int rsid1, int rsid2) return ret; } -static int __init -__init_channel_subsystem(struct subchannel_id schid, void *data) -{ - struct subchannel *sch; - int ret; - - if (cio_is_console(schid)) - sch = cio_get_console_subchannel(); - else { - sch = css_alloc_subchannel(schid); - if (IS_ERR(sch)) - ret = PTR_ERR(sch); - else - ret = 0; - switch (ret) { - case 0: - break; - case -ENOMEM: - panic("Out of memory in init_channel_subsystem\n"); - /* -ENXIO: no more subchannels. */ - case -ENXIO: - return ret; - default: - return 0; - } - } - /* - * We register ALL valid subchannels in ioinfo, even those - * that have been present before init_channel_subsystem. - * These subchannels can't have been registered yet (kmalloc - * not working) so we do it now. This is true e.g. for the - * console subchannel. - */ - css_register_subchannel(sch); - return 0; -} - static void __init -css_generate_pgid(struct channel_subsystem *css, u32 tod_high) +css_generate_pgid(void) { - if (css_characteristics_avail && css_general_characteristics.mcss) { - css->global_pgid.pgid_high.ext_cssid.version = 0x80; - css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; - } else { + /* Let's build our path group ID here. */ + if (css_characteristics_avail && css_general_characteristics.mcss) + global_pgid.cpu_addr = 0x8000; + else { #ifdef CONFIG_SMP - css->global_pgid.pgid_high.cpu_addr = hard_smp_processor_id(); + global_pgid.cpu_addr = hard_smp_processor_id(); #else - css->global_pgid.pgid_high.cpu_addr = 0; + global_pgid.cpu_addr = 0; #endif } - css->global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident; - css->global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine; - css->global_pgid.tod_high = tod_high; - -} - -static void -channel_subsystem_release(struct device *dev) -{ - struct channel_subsystem *css; - - css = to_css(dev); - kfree(css); -} - -static inline void __init -setup_css(int nr) -{ - u32 tod_high; - - memset(css[nr], 0, sizeof(struct channel_subsystem)); - css[nr]->valid = 1; - css[nr]->cssid = nr; - sprintf(css[nr]->device.bus_id, "css%x", nr); - css[nr]->device.release = channel_subsystem_release; - tod_high = (u32) (get_clock() >> 32); - css_generate_pgid(css[nr], tod_high); + global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident; + global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine; + global_pgid.tod_high = (__u32) (get_clock() >> 32); } /* @@ -475,50 +404,53 @@ setup_css(int nr) static int __init init_channel_subsystem (void) { - int ret, i; + int ret, irq; if (chsc_determine_css_characteristics() == 0) css_characteristics_avail = 1; + css_generate_pgid(); + if ((ret = bus_register(&css_bus_type))) goto out; - - /* Try to enable MSS. */ - ret = chsc_enable_facility(CHSC_SDA_OC_MSS); - switch (ret) { - case 0: /* Success. */ - max_ssid = __MAX_SSID; - break; - case -ENOMEM: + if ((ret = device_register (&css_bus_device))) goto out_bus; - default: - max_ssid = 0; - } - /* Setup css structure. */ - for (i = 0; i <= __MAX_CSSID; i++) { - css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); - if (!css[i]) { - ret = -ENOMEM; - goto out_unregister; - } - setup_css(i); - ret = device_register(&css[i]->device); - if (ret) - goto out_free; - } + css_init_done = 1; ctl_set_bit(6, 28); - for_each_subchannel(__init_channel_subsystem, NULL); - return 0; -out_free: - kfree(css[i]); -out_unregister: - while (i > 0) { - i--; - device_unregister(&css[i]->device); + for (irq = 0; irq < __MAX_SUBCHANNELS; irq++) { + struct subchannel *sch; + + if (cio_is_console(irq)) + sch = cio_get_console_subchannel(); + else { + sch = css_alloc_subchannel(irq); + if (IS_ERR(sch)) + ret = PTR_ERR(sch); + else + ret = 0; + if (ret == -ENOMEM) + panic("Out of memory in " + "init_channel_subsystem\n"); + /* -ENXIO: no more subchannels. */ + if (ret == -ENXIO) + break; + if (ret) + continue; + } + /* + * We register ALL valid subchannels in ioinfo, even those + * that have been present before init_channel_subsystem. + * These subchannels can't have been registered yet (kmalloc + * not working) so we do it now. This is true e.g. for the + * console subchannel. + */ + css_register_subchannel(sch); } + return 0; + out_bus: bus_unregister(&css_bus_type); out: @@ -549,8 +481,47 @@ struct bus_type css_bus_type = { subsys_initcall(init_channel_subsystem); +/* + * Register root devices for some drivers. The release function must not be + * in the device drivers, so we do it here. + */ +static void +s390_root_dev_release(struct device *dev) +{ + kfree(dev); +} + +struct device * +s390_root_dev_register(const char *name) +{ + struct device *dev; + int ret; + + if (!strlen(name)) + return ERR_PTR(-EINVAL); + dev = kmalloc(sizeof(struct device), GFP_KERNEL); + if (!dev) + return ERR_PTR(-ENOMEM); + memset(dev, 0, sizeof(struct device)); + strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE)); + dev->release = s390_root_dev_release; + ret = device_register(dev); + if (ret) { + kfree(dev); + return ERR_PTR(ret); + } + return dev; +} + +void +s390_root_dev_unregister(struct device *dev) +{ + if (dev) + device_unregister(dev); +} + int -css_enqueue_subchannel_slow(struct subchannel_id schid) +css_enqueue_subchannel_slow(unsigned long schid) { struct slow_subchannel *new_slow_sch; unsigned long flags; @@ -593,4 +564,6 @@ css_slow_subchannels_exist(void) MODULE_LICENSE("GPL"); EXPORT_SYMBOL(css_bus_type); +EXPORT_SYMBOL(s390_root_dev_register); +EXPORT_SYMBOL(s390_root_dev_unregister); EXPORT_SYMBOL_GPL(css_characteristics_avail); diff --git a/trunk/drivers/s390/cio/css.h b/trunk/drivers/s390/cio/css.h index 251ebd7a7d3a..2004a6c49388 100644 --- a/trunk/drivers/s390/cio/css.h +++ b/trunk/drivers/s390/cio/css.h @@ -6,8 +6,6 @@ #include -#include "schid.h" - /* * path grouping stuff */ @@ -35,25 +33,19 @@ struct path_state { __u8 resvd : 3; /* reserved */ } __attribute__ ((packed)); -struct extended_cssid { - u8 version; - u8 cssid; -} __attribute__ ((packed)); - struct pgid { union { __u8 fc; /* SPID function code */ struct path_state ps; /* SNID path state */ } inf; - union { - __u32 cpu_addr : 16; /* CPU address */ - struct extended_cssid ext_cssid; - } pgid_high; + __u32 cpu_addr : 16; /* CPU address */ __u32 cpu_id : 24; /* CPU identification */ __u32 cpu_model : 16; /* CPU model */ __u32 tod_high; /* high word TOD clock */ } __attribute__ ((packed)); +extern struct pgid global_pgid; + #define MAX_CIWS 8 /* @@ -76,8 +68,7 @@ struct ccw_device_private { atomic_t onoff; unsigned long registered; __u16 devno; /* device number */ - __u16 sch_no; /* subchannel number */ - __u8 ssid; /* subchannel set id */ + __u16 irq; /* subchannel number */ __u8 imask; /* lpm mask for SNID/SID/SPGID */ int iretry; /* retry counter SNID/SID/SPGID */ struct { @@ -130,27 +121,15 @@ struct css_driver { extern struct bus_type css_bus_type; extern struct css_driver io_subchannel_driver; -extern int css_probe_device(struct subchannel_id); -extern struct subchannel * get_subchannel_by_schid(struct subchannel_id); +int css_probe_device(int irq); +extern struct subchannel * get_subchannel_by_schid(int irq); +extern unsigned int highest_subchannel; extern int css_init_done; -extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); - -#define __MAX_SUBCHANNEL 65535 -#define __MAX_SSID 3 -#define __MAX_CHPID 255 -#define __MAX_CSSID 0 - -struct channel_subsystem { - u8 cssid; - int valid; - struct channel_path *chps[__MAX_CHPID]; - struct device device; - struct pgid global_pgid; -}; -#define to_css(dev) container_of(dev, struct channel_subsystem, device) + +#define __MAX_SUBCHANNELS 65536 extern struct bus_type css_bus_type; -extern struct channel_subsystem *css[]; +extern struct device css_bus_device; /* Some helper functions for disconnected state. */ int device_is_disconnected(struct subchannel *); @@ -165,7 +144,7 @@ void device_set_waiting(struct subchannel *); void device_kill_pending_timer(struct subchannel *); /* Helper functions to build lists for the slow path. */ -extern int css_enqueue_subchannel_slow(struct subchannel_id schid); +int css_enqueue_subchannel_slow(unsigned long schid); void css_walk_subchannel_slow_list(void (*fn)(unsigned long)); void css_clear_subchannel_slow_list(void); int css_slow_subchannels_exist(void); diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index fa3e4c0a2536..85908cacc3b8 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.137 $ + * $Revision: 1.131 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -374,7 +374,7 @@ online_store (struct device *dev, struct device_attribute *attr, const char *buf int i, force, ret; char *tmp; - if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0) + if (atomic_compare_and_swap(0, 1, &cdev->private->onoff)) return -EAGAIN; if (cdev->drv && !try_module_get(cdev->drv->owner)) { @@ -535,8 +535,7 @@ ccw_device_register(struct ccw_device *cdev) } struct match_data { - unsigned int devno; - unsigned int ssid; + unsigned int devno; struct ccw_device * sibling; }; @@ -549,7 +548,6 @@ match_devno(struct device * dev, void * data) cdev = to_ccwdev(dev); if ((cdev->private->state == DEV_STATE_DISCONNECTED) && (cdev->private->devno == d->devno) && - (cdev->private->ssid == d->ssid) && (cdev != d->sibling)) { cdev->private->state = DEV_STATE_NOT_OPER; return 1; @@ -558,13 +556,11 @@ match_devno(struct device * dev, void * data) } static struct ccw_device * -get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid, - struct ccw_device *sibling) +get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling) { struct device *dev; struct match_data data = { - .devno = devno, - .ssid = ssid, + .devno = devno, .sibling = sibling, }; @@ -620,13 +616,13 @@ ccw_device_do_unreg_rereg(void *data) need_rename = 1; other_cdev = get_disc_ccwdev_by_devno(sch->schib.pmcw.dev, - sch->schid.ssid, cdev); + cdev); if (other_cdev) { struct subchannel *other_sch; other_sch = to_subchannel(other_cdev->dev.parent); if (get_device(&other_sch->dev)) { - stsch(other_sch->schid, &other_sch->schib); + stsch(other_sch->irq, &other_sch->schib); if (other_sch->schib.pmcw.dnv) { other_sch->schib.pmcw.intparm = 0; cio_modify(other_sch); @@ -643,8 +639,8 @@ ccw_device_do_unreg_rereg(void *data) if (test_and_clear_bit(1, &cdev->private->registered)) device_del(&cdev->dev); if (need_rename) - snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", - sch->schid.ssid, sch->schib.pmcw.dev); + snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", + sch->schib.pmcw.dev); PREPARE_WORK(&cdev->private->kick_work, ccw_device_add_changed, (void *)cdev); queue_work(ccw_device_work, &cdev->private->kick_work); @@ -773,20 +769,18 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) sch->dev.driver_data = cdev; sch->driver = &io_subchannel_driver; cdev->ccwlock = &sch->lock; - /* Init private data. */ priv = cdev->private; priv->devno = sch->schib.pmcw.dev; - priv->ssid = sch->schid.ssid; - priv->sch_no = sch->schid.sch_no; + priv->irq = sch->irq; priv->state = DEV_STATE_NOT_OPER; INIT_LIST_HEAD(&priv->cmb_list); init_waitqueue_head(&priv->wait_q); init_timer(&priv->timer); /* Set an initial name for the device. */ - snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.%x.%04x", - sch->schid.ssid, sch->schib.pmcw.dev); + snprintf (cdev->dev.bus_id, BUS_ID_SIZE, "0.0.%04x", + sch->schib.pmcw.dev); /* Increase counter of devices currently in recognition. */ atomic_inc(&ccw_device_init_count); @@ -957,7 +951,7 @@ io_subchannel_shutdown(struct device *dev) sch = to_subchannel(dev); cdev = dev->driver_data; - if (cio_is_console(sch->schid)) + if (cio_is_console(sch->irq)) return; if (!sch->schib.pmcw.ena) /* Nothing to do. */ @@ -992,6 +986,10 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch) cdev->dev = (struct device) { .parent = &sch->dev, }; + /* Initialize the subchannel structure */ + sch->dev.parent = &css_bus_device; + sch->dev.bus = &css_bus_type; + rc = io_subchannel_recog(cdev, sch); if (rc) return rc; @@ -1148,16 +1146,6 @@ ccw_driver_unregister (struct ccw_driver *cdriver) driver_unregister(&cdriver->driver); } -/* Helper func for qdio. */ -struct subchannel_id -ccw_device_get_subchannel_id(struct ccw_device *cdev) -{ - struct subchannel *sch; - - sch = to_subchannel(cdev->dev.parent); - return sch->schid; -} - MODULE_LICENSE("GPL"); EXPORT_SYMBOL(ccw_device_set_online); EXPORT_SYMBOL(ccw_device_set_offline); @@ -1167,4 +1155,3 @@ EXPORT_SYMBOL(get_ccwdev_by_busid); EXPORT_SYMBOL(ccw_bus_type); EXPORT_SYMBOL(ccw_device_work); EXPORT_SYMBOL(ccw_device_notify_work); -EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); diff --git a/trunk/drivers/s390/cio/device.h b/trunk/drivers/s390/cio/device.h index 11587ebb7289..a3aa056d7245 100644 --- a/trunk/drivers/s390/cio/device.h +++ b/trunk/drivers/s390/cio/device.h @@ -110,7 +110,6 @@ int ccw_device_stlck(struct ccw_device *); /* qdio needs this. */ void ccw_device_set_timeout(struct ccw_device *, int); -extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *); void retry_set_schib(struct ccw_device *cdev); #endif diff --git a/trunk/drivers/s390/cio/device_fsm.c b/trunk/drivers/s390/cio/device_fsm.c index 23d12b65e5fa..c1c89f4fd4e3 100644 --- a/trunk/drivers/s390/cio/device_fsm.c +++ b/trunk/drivers/s390/cio/device_fsm.c @@ -133,7 +133,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev) int ret; sch = to_subchannel(cdev->dev.parent); - ret = stsch(sch->schid, &sch->schib); + ret = stsch(sch->irq, &sch->schib); if (ret || !sch->schib.pmcw.dnv) return -ENODEV; if (!sch->schib.pmcw.ena || sch->schib.scsw.actl == 0) @@ -231,7 +231,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) * through ssch() and the path information is up to date. */ old_lpm = sch->lpm; - stsch(sch->schid, &sch->schib); + stsch(sch->irq, &sch->schib); sch->lpm = sch->schib.pmcw.pim & sch->schib.pmcw.pam & sch->schib.pmcw.pom & @@ -257,9 +257,8 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) switch (state) { case DEV_STATE_NOT_OPER: CIO_DEBUG(KERN_WARNING, 2, - "SenseID : unknown device %04x on subchannel " - "0.%x.%04x\n", cdev->private->devno, - sch->schid.ssid, sch->schid.sch_no); + "SenseID : unknown device %04x on subchannel %04x\n", + cdev->private->devno, sch->irq); break; case DEV_STATE_OFFLINE: if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { @@ -283,18 +282,16 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) return; } /* Issue device info message. */ - CIO_DEBUG(KERN_INFO, 2, "SenseID : device 0.%x.%04x reports: " + CIO_DEBUG(KERN_INFO, 2, "SenseID : device %04x reports: " "CU Type/Mod = %04X/%02X, Dev Type/Mod = " - "%04X/%02X\n", - cdev->private->ssid, cdev->private->devno, + "%04X/%02X\n", cdev->private->devno, cdev->id.cu_type, cdev->id.cu_model, cdev->id.dev_type, cdev->id.dev_model); break; case DEV_STATE_BOXED: CIO_DEBUG(KERN_WARNING, 2, - "SenseID : boxed device %04x on subchannel " - "0.%x.%04x\n", cdev->private->devno, - sch->schid.ssid, sch->schid.sch_no); + "SenseID : boxed device %04x on subchannel %04x\n", + cdev->private->devno, sch->irq); break; } cdev->private->state = state; @@ -362,7 +359,7 @@ ccw_device_done(struct ccw_device *cdev, int state) if (state == DEV_STATE_BOXED) CIO_DEBUG(KERN_WARNING, 2, "Boxed device %04x on subchannel %04x\n", - cdev->private->devno, sch->schid.sch_no); + cdev->private->devno, sch->irq); if (cdev->private->flags.donotify) { cdev->private->flags.donotify = 0; @@ -595,7 +592,7 @@ ccw_device_offline(struct ccw_device *cdev) struct subchannel *sch; sch = to_subchannel(cdev->dev.parent); - if (stsch(sch->schid, &sch->schib) || !sch->schib.pmcw.dnv) + if (stsch(sch->irq, &sch->schib) || !sch->schib.pmcw.dnv) return -ENODEV; if (cdev->private->state != DEV_STATE_ONLINE) { if (sch->schib.scsw.actl != 0) @@ -714,7 +711,7 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event) * Since we might not just be coming from an interrupt from the * subchannel we have to update the schib. */ - stsch(sch->schid, &sch->schib); + stsch(sch->irq, &sch->schib); if (sch->schib.scsw.actl != 0 || (cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) { @@ -926,7 +923,7 @@ ccw_device_wait4io_irq(struct ccw_device *cdev, enum dev_event dev_event) /* Iff device is idle, reset timeout. */ sch = to_subchannel(cdev->dev.parent); - if (!stsch(sch->schid, &sch->schib)) + if (!stsch(sch->irq, &sch->schib)) if (sch->schib.scsw.actl == 0) ccw_device_set_timeout(cdev, 0); /* Call the handler. */ @@ -1038,7 +1035,7 @@ device_trigger_reprobe(struct subchannel *sch) return; /* Update some values. */ - if (stsch(sch->schid, &sch->schib)) + if (stsch(sch->irq, &sch->schib)) return; /* diff --git a/trunk/drivers/s390/cio/device_id.c b/trunk/drivers/s390/cio/device_id.c index 04ceba343db8..0e68fb511dc9 100644 --- a/trunk/drivers/s390/cio/device_id.c +++ b/trunk/drivers/s390/cio/device_id.c @@ -27,7 +27,7 @@ /* * diag210 is used under VM to get information about a virtual device */ -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X int diag210(struct diag210 * addr) { @@ -256,17 +256,16 @@ ccw_device_check_sense_id(struct ccw_device *cdev) * sense id information. So, for intervention required, * we use the "whack it until it talks" strategy... */ - CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel " - "0.%x.%04x reports cmd reject\n", - cdev->private->devno, sch->schid.ssid, - sch->schid.sch_no); + CIO_MSG_EVENT(2, "SenseID : device %04x on Subchannel %04x " + "reports cmd reject\n", + cdev->private->devno, sch->irq); return -EOPNOTSUPP; } if (irb->esw.esw0.erw.cons) { - CIO_MSG_EVENT(2, "SenseID : UC on dev 0.%x.%04x, " + CIO_MSG_EVENT(2, "SenseID : UC on dev %04x, " "lpum %02X, cnt %02d, sns :" " %02X%02X%02X%02X %02X%02X%02X%02X ...\n", - cdev->private->ssid, cdev->private->devno, + cdev->private->devno, irb->esw.esw0.sublog.lpum, irb->esw.esw0.erw.scnt, irb->ecw[0], irb->ecw[1], @@ -278,17 +277,16 @@ ccw_device_check_sense_id(struct ccw_device *cdev) if (irb->scsw.cc == 3) { if ((sch->orb.lpm & sch->schib.pmcw.pim & sch->schib.pmcw.pam) != 0) - CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x " - "on subchannel 0.%x.%04x is " - "'not operational'\n", sch->orb.lpm, - cdev->private->devno, sch->schid.ssid, - sch->schid.sch_no); + CIO_MSG_EVENT(2, "SenseID : path %02X for device %04x on" + " subchannel %04x is 'not operational'\n", + sch->orb.lpm, cdev->private->devno, + sch->irq); return -EACCES; } /* Hmm, whatever happened, try again. */ CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on " - "subchannel 0.%x.%04x returns status %02X%02X\n", - cdev->private->devno, sch->schid.ssid, sch->schid.sch_no, + "subchannel %04x returns status %02X%02X\n", + cdev->private->devno, sch->irq, irb->scsw.dstat, irb->scsw.cstat); return -EAGAIN; } diff --git a/trunk/drivers/s390/cio/device_ops.c b/trunk/drivers/s390/cio/device_ops.c index 143b6c25a4e6..85a3026e6900 100644 --- a/trunk/drivers/s390/cio/device_ops.c +++ b/trunk/drivers/s390/cio/device_ops.c @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device_ops.c * - * $Revision: 1.58 $ + * $Revision: 1.57 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -570,7 +570,7 @@ ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) int _ccw_device_get_subchannel_number(struct ccw_device *cdev) { - return cdev->private->sch_no; + return cdev->private->irq; } int diff --git a/trunk/drivers/s390/cio/device_pgid.c b/trunk/drivers/s390/cio/device_pgid.c index 052832d03d38..0adac8a67331 100644 --- a/trunk/drivers/s390/cio/device_pgid.c +++ b/trunk/drivers/s390/cio/device_pgid.c @@ -22,7 +22,6 @@ #include "cio_debug.h" #include "css.h" #include "device.h" -#include "ioasm.h" /* * Start Sense Path Group ID helper function. Used in ccw_device_recog @@ -57,10 +56,10 @@ __ccw_device_sense_pgid_start(struct ccw_device *cdev) if (ret != -EACCES) return ret; CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel " - "0.%x.%04x, lpm %02X, became 'not " + "%04x, lpm %02X, became 'not " "operational'\n", - cdev->private->devno, sch->schid.ssid, - sch->schid.sch_no, cdev->private->imask); + cdev->private->devno, sch->irq, + cdev->private->imask); } cdev->private->imask >>= 1; @@ -106,10 +105,10 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev) return -EOPNOTSUPP; } if (irb->esw.esw0.erw.cons) { - CIO_MSG_EVENT(2, "SNID - device 0.%x.%04x, unit check, " + CIO_MSG_EVENT(2, "SNID - device %04x, unit check, " "lpum %02X, cnt %02d, sns : " "%02X%02X%02X%02X %02X%02X%02X%02X ...\n", - cdev->private->ssid, cdev->private->devno, + cdev->private->devno, irb->esw.esw0.sublog.lpum, irb->esw.esw0.erw.scnt, irb->ecw[0], irb->ecw[1], @@ -119,17 +118,15 @@ __ccw_device_check_sense_pgid(struct ccw_device *cdev) return -EAGAIN; } if (irb->scsw.cc == 3) { - CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x," - " lpm %02X, became 'not operational'\n", - cdev->private->devno, sch->schid.ssid, - sch->schid.sch_no, sch->orb.lpm); + CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel " + "%04x, lpm %02X, became 'not operational'\n", + cdev->private->devno, sch->irq, sch->orb.lpm); return -EACCES; } if (cdev->private->pgid.inf.ps.state2 == SNID_STATE2_RESVD_ELSE) { - CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel 0.%x.%04x " + CIO_MSG_EVENT(2, "SNID - Device %04x on Subchannel %04x " "is reserved by someone else\n", - cdev->private->devno, sch->schid.ssid, - sch->schid.sch_no); + cdev->private->devno, sch->irq); return -EUSERS; } return 0; @@ -165,7 +162,7 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event) /* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */ case 0: /* Sense Path Group ID successful. */ if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET) - memcpy(&cdev->private->pgid, &css[0]->global_pgid, + memcpy(&cdev->private->pgid, &global_pgid, sizeof(struct pgid)); ccw_device_sense_pgid_done(cdev, 0); break; @@ -238,9 +235,8 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func) sch->lpm &= ~cdev->private->imask; sch->vpm &= ~cdev->private->imask; CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " - "0.%x.%04x, lpm %02X, became 'not operational'\n", - cdev->private->devno, sch->schid.ssid, - sch->schid.sch_no, cdev->private->imask); + "%04x, lpm %02X, became 'not operational'\n", + cdev->private->devno, sch->irq, cdev->private->imask); return ret; } @@ -262,10 +258,8 @@ __ccw_device_check_pgid(struct ccw_device *cdev) if (irb->ecw[0] & SNS0_CMD_REJECT) return -EOPNOTSUPP; /* Hmm, whatever happened, try again. */ - CIO_MSG_EVENT(2, "SPID - device 0.%x.%04x, unit check, " - "cnt %02d, " + CIO_MSG_EVENT(2, "SPID - device %04x, unit check, cnt %02d, " "sns : %02X%02X%02X%02X %02X%02X%02X%02X ...\n", - cdev->private->ssid, cdev->private->devno, irb->esw.esw0.erw.scnt, irb->ecw[0], irb->ecw[1], irb->ecw[2], irb->ecw[3], @@ -274,10 +268,10 @@ __ccw_device_check_pgid(struct ccw_device *cdev) return -EAGAIN; } if (irb->scsw.cc == 3) { - CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel 0.%x.%04x," - " lpm %02X, became 'not operational'\n", - cdev->private->devno, sch->schid.ssid, - sch->schid.sch_no, cdev->private->imask); + CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " + "%04x, lpm %02X, became 'not operational'\n", + cdev->private->devno, sch->irq, + cdev->private->imask); return -EACCES; } return 0; @@ -370,22 +364,8 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event) void ccw_device_verify_start(struct ccw_device *cdev) { - struct subchannel *sch = to_subchannel(cdev->dev.parent); - cdev->private->flags.pgid_single = 0; cdev->private->iretry = 5; - /* - * Update sch->lpm with current values to catch paths becoming - * available again. - */ - if (stsch(sch->schid, &sch->schib)) { - ccw_device_verify_done(cdev, -ENODEV); - return; - } - sch->lpm = sch->schib.pmcw.pim & - sch->schib.pmcw.pam & - sch->schib.pmcw.pom & - sch->opm; __ccw_device_verify_start(cdev); } diff --git a/trunk/drivers/s390/cio/device_status.c b/trunk/drivers/s390/cio/device_status.c index db09c209098b..12a24d4331a2 100644 --- a/trunk/drivers/s390/cio/device_status.c +++ b/trunk/drivers/s390/cio/device_status.c @@ -36,16 +36,15 @@ ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb) CIO_MSG_EVENT(0, "Channel-Check or Interface-Control-Check " "received" - " ... device %04x on subchannel 0.%x.%04x, dev_stat " + " ... device %04X on subchannel %04X, dev_stat " ": %02X sch_stat : %02X\n", - cdev->private->devno, cdev->private->ssid, - cdev->private->sch_no, + cdev->private->devno, cdev->private->irq, irb->scsw.dstat, irb->scsw.cstat); if (irb->scsw.cc != 3) { char dbf_text[15]; - sprintf(dbf_text, "chk%x", cdev->private->sch_no); + sprintf(dbf_text, "chk%x", cdev->private->irq); CIO_TRACE_EVENT(0, dbf_text); CIO_HEX_EVENT(0, irb, sizeof (struct irb)); } @@ -60,11 +59,10 @@ ccw_device_path_notoper(struct ccw_device *cdev) struct subchannel *sch; sch = to_subchannel(cdev->dev.parent); - stsch (sch->schid, &sch->schib); + stsch (sch->irq, &sch->schib); - CIO_MSG_EVENT(0, "%s(0.%x.%04x) - path(s) %02x are " - "not operational \n", __FUNCTION__, - sch->schid.ssid, sch->schid.sch_no, + CIO_MSG_EVENT(0, "%s(%04x) - path(s) %02x are " + "not operational \n", __FUNCTION__, sch->irq, sch->schib.pmcw.pnom); sch->lpm &= ~sch->schib.pmcw.pnom; diff --git a/trunk/drivers/s390/cio/ioasm.h b/trunk/drivers/s390/cio/ioasm.h index 95a9462f9a91..45480a2bc4c0 100644 --- a/trunk/drivers/s390/cio/ioasm.h +++ b/trunk/drivers/s390/cio/ioasm.h @@ -1,13 +1,12 @@ #ifndef S390_CIO_IOASM_H #define S390_CIO_IOASM_H -#include "schid.h" - /* * TPI info structure */ struct tpi_info { - struct subchannel_id schid; + __u32 reserved1 : 16; /* reserved 0x00000001 */ + __u32 irq : 16; /* aka. subchannel number */ __u32 intparm; /* interruption parameter */ __u32 adapter_IO : 1; __u32 reserved2 : 1; @@ -22,8 +21,7 @@ struct tpi_info { * Some S390 specific IO instructions as inline */ -static inline int stsch(struct subchannel_id schid, - volatile struct schib *addr) +static inline int stsch(int irq, volatile struct schib *addr) { int ccode; @@ -33,42 +31,12 @@ static inline int stsch(struct subchannel_id schid, " ipm %0\n" " srl %0,28" : "=d" (ccode) - : "d" (schid), "a" (addr), "m" (*addr) - : "cc", "1" ); - return ccode; -} - -static inline int stsch_err(struct subchannel_id schid, - volatile struct schib *addr) -{ - int ccode; - - __asm__ __volatile__( - " lhi %0,%3\n" - " lr 1,%1\n" - " stsch 0(%2)\n" - "0: ipm %0\n" - " srl %0,28\n" - "1:\n" -#ifdef CONFIG_64BIT - ".section __ex_table,\"a\"\n" - " .align 8\n" - " .quad 0b,1b\n" - ".previous" -#else - ".section __ex_table,\"a\"\n" - " .align 4\n" - " .long 0b,1b\n" - ".previous" -#endif - : "=&d" (ccode) - : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr) + : "d" (irq | 0x10000), "a" (addr) : "cc", "1" ); return ccode; } -static inline int msch(struct subchannel_id schid, - volatile struct schib *addr) +static inline int msch(int irq, volatile struct schib *addr) { int ccode; @@ -78,13 +46,12 @@ static inline int msch(struct subchannel_id schid, " ipm %0\n" " srl %0,28" : "=d" (ccode) - : "d" (schid), "a" (addr), "m" (*addr) + : "d" (irq | 0x10000L), "a" (addr) : "cc", "1" ); return ccode; } -static inline int msch_err(struct subchannel_id schid, - volatile struct schib *addr) +static inline int msch_err(int irq, volatile struct schib *addr) { int ccode; @@ -95,7 +62,7 @@ static inline int msch_err(struct subchannel_id schid, "0: ipm %0\n" " srl %0,28\n" "1:\n" -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X ".section __ex_table,\"a\"\n" " .align 8\n" " .quad 0b,1b\n" @@ -107,13 +74,12 @@ static inline int msch_err(struct subchannel_id schid, ".previous" #endif : "=&d" (ccode) - : "d" (schid), "a" (addr), "K" (-EIO), "m" (*addr) + : "d" (irq | 0x10000L), "a" (addr), "K" (-EIO) : "cc", "1" ); return ccode; } -static inline int tsch(struct subchannel_id schid, - volatile struct irb *addr) +static inline int tsch(int irq, volatile struct irb *addr) { int ccode; @@ -123,7 +89,7 @@ static inline int tsch(struct subchannel_id schid, " ipm %0\n" " srl %0,28" : "=d" (ccode) - : "d" (schid), "a" (addr), "m" (*addr) + : "d" (irq | 0x10000L), "a" (addr) : "cc", "1" ); return ccode; } @@ -137,13 +103,12 @@ static inline int tpi( volatile struct tpi_info *addr) " ipm %0\n" " srl %0,28" : "=d" (ccode) - : "a" (addr), "m" (*addr) + : "a" (addr) : "cc", "1" ); return ccode; } -static inline int ssch(struct subchannel_id schid, - volatile struct orb *addr) +static inline int ssch(int irq, volatile struct orb *addr) { int ccode; @@ -153,12 +118,12 @@ static inline int ssch(struct subchannel_id schid, " ipm %0\n" " srl %0,28" : "=d" (ccode) - : "d" (schid), "a" (addr), "m" (*addr) + : "d" (irq | 0x10000L), "a" (addr) : "cc", "1" ); return ccode; } -static inline int rsch(struct subchannel_id schid) +static inline int rsch(int irq) { int ccode; @@ -168,12 +133,12 @@ static inline int rsch(struct subchannel_id schid) " ipm %0\n" " srl %0,28" : "=d" (ccode) - : "d" (schid) + : "d" (irq | 0x10000L) : "cc", "1" ); return ccode; } -static inline int csch(struct subchannel_id schid) +static inline int csch(int irq) { int ccode; @@ -183,12 +148,12 @@ static inline int csch(struct subchannel_id schid) " ipm %0\n" " srl %0,28" : "=d" (ccode) - : "d" (schid) + : "d" (irq | 0x10000L) : "cc", "1" ); return ccode; } -static inline int hsch(struct subchannel_id schid) +static inline int hsch(int irq) { int ccode; @@ -198,12 +163,12 @@ static inline int hsch(struct subchannel_id schid) " ipm %0\n" " srl %0,28" : "=d" (ccode) - : "d" (schid) + : "d" (irq | 0x10000L) : "cc", "1" ); return ccode; } -static inline int xsch(struct subchannel_id schid) +static inline int xsch(int irq) { int ccode; @@ -213,22 +178,21 @@ static inline int xsch(struct subchannel_id schid) " ipm %0\n" " srl %0,28" : "=d" (ccode) - : "d" (schid) + : "d" (irq | 0x10000L) : "cc", "1" ); return ccode; } static inline int chsc(void *chsc_area) { - typedef struct { char _[4096]; } addr_type; int cc; __asm__ __volatile__ ( - ".insn rre,0xb25f0000,%2,0 \n\t" + ".insn rre,0xb25f0000,%1,0 \n\t" "ipm %0 \n\t" "srl %0,28 \n\t" - : "=d" (cc), "=m" (*(addr_type *) chsc_area) - : "d" (chsc_area), "m" (*(addr_type *) chsc_area) + : "=d" (cc) + : "d" (chsc_area) : "cc" ); return cc; diff --git a/trunk/drivers/s390/cio/qdio.c b/trunk/drivers/s390/cio/qdio.c index 30a836ffc31f..eb39218b925e 100644 --- a/trunk/drivers/s390/cio/qdio.c +++ b/trunk/drivers/s390/cio/qdio.c @@ -56,7 +56,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.114 $" +#define VERSION_QDIO_C "$Revision: 1.108 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); @@ -76,7 +76,6 @@ static struct qdio_perf_stats perf_stats; #endif /* QDIO_PERFORMANCE_STATS */ static int hydra_thinints; -static int is_passthrough = 0; static int omit_svs; static int indicator_used[INDICATORS_PER_CACHELINE]; @@ -137,126 +136,12 @@ qdio_release_q(struct qdio_q *q) atomic_dec(&q->use_count); } -/*check ccq */ -static inline int -qdio_check_ccq(struct qdio_q *q, unsigned int ccq) -{ - char dbf_text[15]; - - if (ccq == 0 || ccq == 32 || ccq == 96) - return 0; - if (ccq == 97) - return 1; - /*notify devices immediately*/ - sprintf(dbf_text,"%d", ccq); - QDIO_DBF_TEXT2(1,trace,dbf_text); - return -EIO; -} -/* EQBS: extract buffer states */ -static inline int -qdio_do_eqbs(struct qdio_q *q, unsigned char *state, - unsigned int *start, unsigned int *cnt) -{ - struct qdio_irq *irq; - unsigned int tmp_cnt, q_no, ccq; - int rc ; - char dbf_text[15]; - - ccq = 0; - tmp_cnt = *cnt; - irq = (struct qdio_irq*)q->irq_ptr; - q_no = q->q_no; - if(!q->is_input_q) - q_no += irq->no_input_qs; - ccq = do_eqbs(irq->sch_token, state, q_no, start, cnt); - rc = qdio_check_ccq(q, ccq); - if (rc < 0) { - QDIO_DBF_TEXT2(1,trace,"eqberr"); - sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt, *cnt, ccq, q_no); - QDIO_DBF_TEXT2(1,trace,dbf_text); - q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION| - QDIO_STATUS_LOOK_FOR_ERROR, - 0, 0, 0, -1, -1, q->int_parm); - return 0; - } - return (tmp_cnt - *cnt); -} - -/* SQBS: set buffer states */ -static inline int -qdio_do_sqbs(struct qdio_q *q, unsigned char state, - unsigned int *start, unsigned int *cnt) +static volatile inline void +qdio_set_slsb(volatile char *slsb, unsigned char value) { - struct qdio_irq *irq; - unsigned int tmp_cnt, q_no, ccq; - int rc; - char dbf_text[15]; - - ccq = 0; - tmp_cnt = *cnt; - irq = (struct qdio_irq*)q->irq_ptr; - q_no = q->q_no; - if(!q->is_input_q) - q_no += irq->no_input_qs; - ccq = do_sqbs(irq->sch_token, state, q_no, start, cnt); - rc = qdio_check_ccq(q, ccq); - if (rc < 0) { - QDIO_DBF_TEXT3(1,trace,"sqberr"); - sprintf(dbf_text,"%2x,%2x,%d,%d",tmp_cnt,*cnt,ccq,q_no); - QDIO_DBF_TEXT3(1,trace,dbf_text); - q->handler(q->cdev,QDIO_STATUS_ACTIVATE_CHECK_CONDITION| - QDIO_STATUS_LOOK_FOR_ERROR, - 0, 0, 0, -1, -1, q->int_parm); - return 0; - } - return (tmp_cnt - *cnt); + xchg((char*)slsb,value); } -static inline int -qdio_set_slsb(struct qdio_q *q, unsigned int *bufno, - unsigned char state, unsigned int *count) -{ - volatile char *slsb; - struct qdio_irq *irq; - - irq = (struct qdio_irq*)q->irq_ptr; - if (!irq->is_qebsm) { - slsb = (char *)&q->slsb.acc.val[(*bufno)]; - xchg(slsb, state); - return 1; - } - return qdio_do_sqbs(q, state, bufno, count); -} - -#ifdef CONFIG_QDIO_DEBUG -static inline void -qdio_trace_slsb(struct qdio_q *q) -{ - if (q->queue_type==QDIO_TRACE_QTYPE) { - if (q->is_input_q) - QDIO_DBF_HEX2(0,slsb_in,&q->slsb, - QDIO_MAX_BUFFERS_PER_Q); - else - QDIO_DBF_HEX2(0,slsb_out,&q->slsb, - QDIO_MAX_BUFFERS_PER_Q); - } -} -#endif - -static inline int -set_slsb(struct qdio_q *q, unsigned int *bufno, - unsigned char state, unsigned int *count) -{ - int rc; -#ifdef CONFIG_QDIO_DEBUG - qdio_trace_slsb(q); -#endif - rc = qdio_set_slsb(q, bufno, state, count); -#ifdef CONFIG_QDIO_DEBUG - qdio_trace_slsb(q); -#endif - return rc; -} static inline int qdio_siga_sync(struct qdio_q *q, unsigned int gpr2, unsigned int gpr3) @@ -270,7 +155,7 @@ qdio_siga_sync(struct qdio_q *q, unsigned int gpr2, perf_stats.siga_syncs++; #endif /* QDIO_PERFORMANCE_STATS */ - cc = do_siga_sync(q->schid, gpr2, gpr3); + cc = do_siga_sync(q->irq, gpr2, gpr3); if (cc) QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*)); @@ -285,23 +170,6 @@ qdio_siga_sync_q(struct qdio_q *q) return qdio_siga_sync(q, q->mask, 0); } -static int -__do_siga_output(struct qdio_q *q, unsigned int *busy_bit) -{ - struct qdio_irq *irq; - unsigned int fc = 0; - unsigned long schid; - - irq = (struct qdio_irq *) q->irq_ptr; - if (!irq->is_qebsm) - schid = *((u32 *)&q->schid); - else { - schid = irq->sch_token; - fc |= 0x80; - } - return do_siga_output(schid, q->mask, busy_bit, fc); -} - /* * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns * an access exception @@ -321,7 +189,7 @@ qdio_siga_output(struct qdio_q *q) QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); for (;;) { - cc = __do_siga_output(q, &busy_bit); + cc = do_siga_output(q->irq, q->mask, &busy_bit); //QDIO_PRINT_ERR("cc=%x, busy=%x\n",cc,busy_bit); if ((cc==2) && (busy_bit) && (q->is_iqdio_q)) { if (!start_time) @@ -353,7 +221,7 @@ qdio_siga_input(struct qdio_q *q) perf_stats.siga_ins++; #endif /* QDIO_PERFORMANCE_STATS */ - cc = do_siga_input(q->schid, q->mask); + cc = do_siga_input(q->irq, q->mask); if (cc) QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*)); @@ -362,7 +230,7 @@ qdio_siga_input(struct qdio_q *q) } /* locked by the locks in qdio_activate and qdio_cleanup */ -static __u32 * +static __u32 volatile * qdio_get_indicator(void) { int i; @@ -390,7 +258,7 @@ qdio_put_indicator(__u32 *addr) atomic_dec(&spare_indicator_usecount); } -static inline void +static inline volatile void tiqdio_clear_summary_bit(__u32 *location) { QDIO_DBF_TEXT5(0,trace,"clrsummb"); @@ -399,7 +267,7 @@ tiqdio_clear_summary_bit(__u32 *location) xchg(location,0); } -static inline void +static inline volatile void tiqdio_set_summary_bit(__u32 *location) { QDIO_DBF_TEXT5(0,trace,"setsummb"); @@ -468,9 +336,7 @@ static inline int qdio_stop_polling(struct qdio_q *q) { #ifdef QDIO_USE_PROCESSING_STATE - unsigned int tmp, gsf, count = 1; - unsigned char state = 0; - struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; + int gsf; if (!atomic_swap(&q->polling,0)) return 1; @@ -482,22 +348,17 @@ qdio_stop_polling(struct qdio_q *q) if (!q->is_input_q) return 1; - tmp = gsf = GET_SAVED_FRONTIER(q); - tmp = ((tmp + QDIO_MAX_BUFFERS_PER_Q-1) & (QDIO_MAX_BUFFERS_PER_Q-1) ); - set_slsb(q, &tmp, SLSB_P_INPUT_NOT_INIT, &count); - + gsf=GET_SAVED_FRONTIER(q); + set_slsb(&q->slsb.acc.val[(gsf+QDIO_MAX_BUFFERS_PER_Q-1)& + (QDIO_MAX_BUFFERS_PER_Q-1)], + SLSB_P_INPUT_NOT_INIT); /* * we don't issue this SYNC_MEMORY, as we trust Rick T and * moreover will not use the PROCESSING state under VM, so * q->polling was 0 anyway */ /*SYNC_MEMORY;*/ - if (irq->is_qebsm) { - count = 1; - qdio_do_eqbs(q, &state, &gsf, &count); - } else - state = q->slsb.acc.val[gsf]; - if (state != SLSB_P_INPUT_PRIMED) + if (q->slsb.acc.val[gsf]!=SLSB_P_INPUT_PRIMED) return 1; /* * set our summary bit again, as otherwise there is a @@ -570,136 +431,18 @@ tiqdio_clear_global_summary(void) /************************* OUTBOUND ROUTINES *******************************/ -static int -qdio_qebsm_get_outbound_buffer_frontier(struct qdio_q *q) -{ - struct qdio_irq *irq; - unsigned char state; - unsigned int cnt, count, ftc; - - irq = (struct qdio_irq *) q->irq_ptr; - if ((!q->is_iqdio_q) && (!q->hydra_gives_outbound_pcis)) - SYNC_MEMORY; - - ftc = q->first_to_check; - count = qdio_min(atomic_read(&q->number_of_buffers_used), - (QDIO_MAX_BUFFERS_PER_Q-1)); - if (count == 0) - return q->first_to_check; - cnt = qdio_do_eqbs(q, &state, &ftc, &count); - if (cnt == 0) - return q->first_to_check; - switch (state) { - case SLSB_P_OUTPUT_ERROR: - QDIO_DBF_TEXT3(0,trace,"outperr"); - atomic_sub(cnt , &q->number_of_buffers_used); - if (q->qdio_error) - q->error_status_flags |= - QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR; - q->qdio_error = SLSB_P_OUTPUT_ERROR; - q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR; - q->first_to_check = ftc; - break; - case SLSB_P_OUTPUT_EMPTY: - QDIO_DBF_TEXT5(0,trace,"outpempt"); - atomic_sub(cnt, &q->number_of_buffers_used); - q->first_to_check = ftc; - break; - case SLSB_CU_OUTPUT_PRIMED: - /* all buffers primed */ - QDIO_DBF_TEXT5(0,trace,"outpprim"); - break; - default: - break; - } - QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); - return q->first_to_check; -} - -static int -qdio_qebsm_get_inbound_buffer_frontier(struct qdio_q *q) -{ - struct qdio_irq *irq; - unsigned char state; - int tmp, ftc, count, cnt; - char dbf_text[15]; - - - irq = (struct qdio_irq *) q->irq_ptr; - ftc = q->first_to_check; - count = qdio_min(atomic_read(&q->number_of_buffers_used), - (QDIO_MAX_BUFFERS_PER_Q-1)); - if (count == 0) - return q->first_to_check; - cnt = qdio_do_eqbs(q, &state, &ftc, &count); - if (cnt == 0) - return q->first_to_check; - switch (state) { - case SLSB_P_INPUT_ERROR : -#ifdef CONFIG_QDIO_DEBUG - QDIO_DBF_TEXT3(1,trace,"inperr"); - sprintf(dbf_text,"%2x,%2x",ftc,count); - QDIO_DBF_TEXT3(1,trace,dbf_text); -#endif /* CONFIG_QDIO_DEBUG */ - if (q->qdio_error) - q->error_status_flags |= - QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR; - q->qdio_error = SLSB_P_INPUT_ERROR; - q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR; - atomic_sub(cnt, &q->number_of_buffers_used); - q->first_to_check = ftc; - break; - case SLSB_P_INPUT_PRIMED : - QDIO_DBF_TEXT3(0,trace,"inptprim"); - sprintf(dbf_text,"%2x,%2x",ftc,count); - QDIO_DBF_TEXT3(1,trace,dbf_text); - tmp = 0; - ftc = q->first_to_check; -#ifdef QDIO_USE_PROCESSING_STATE - if (cnt > 1) { - cnt -= 1; - tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt); - if (!tmp) - break; - } - cnt = 1; - tmp += set_slsb(q, &ftc, - SLSB_P_INPUT_PROCESSING, &cnt); - atomic_set(&q->polling, 1); -#else - tmp = set_slsb(q, &ftc, SLSB_P_INPUT_NOT_INIT, &cnt); -#endif - atomic_sub(tmp, &q->number_of_buffers_used); - q->first_to_check = ftc; - break; - case SLSB_CU_INPUT_EMPTY: - case SLSB_P_INPUT_NOT_INIT: - case SLSB_P_INPUT_PROCESSING: - QDIO_DBF_TEXT5(0,trace,"inpnipro"); - break; - default: - break; - } - QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); - return q->first_to_check; -} static inline int qdio_get_outbound_buffer_frontier(struct qdio_q *q) { - struct qdio_irq *irq; - volatile char *slsb; - unsigned int count = 1; - int first_not_to_check, f, f_mod_no; + int f,f_mod_no; + volatile char *slsb; + int first_not_to_check; char dbf_text[15]; QDIO_DBF_TEXT4(0,trace,"getobfro"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - irq = (struct qdio_irq *) q->irq_ptr; - if (irq->is_qebsm) - return qdio_qebsm_get_outbound_buffer_frontier(q); - slsb=&q->slsb.acc.val[0]; f_mod_no=f=q->first_to_check; /* @@ -741,7 +484,7 @@ qdio_get_outbound_buffer_frontier(struct qdio_q *q) QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256); /* kind of process the buffer */ - set_slsb(q, &f_mod_no, SLSB_P_OUTPUT_NOT_INIT, &count); + set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT); /* * we increment the frontier, as this buffer @@ -854,48 +597,48 @@ qdio_kick_outbound_q(struct qdio_q *q) result=qdio_siga_output(q); - switch (result) { - case 0: - /* went smooth this time, reset timestamp */ + switch (result) { + case 0: + /* went smooth this time, reset timestamp */ #ifdef CONFIG_QDIO_DEBUG - QDIO_DBF_TEXT3(0,trace,"cc2reslv"); - sprintf(dbf_text,"%4x%2x%2x",q->schid.sch_no,q->q_no, - atomic_read(&q->busy_siga_counter)); - QDIO_DBF_TEXT3(0,trace,dbf_text); + QDIO_DBF_TEXT3(0,trace,"cc2reslv"); + sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, + atomic_read(&q->busy_siga_counter)); + QDIO_DBF_TEXT3(0,trace,dbf_text); #endif /* CONFIG_QDIO_DEBUG */ - q->timing.busy_start=0; - break; - case (2|QDIO_SIGA_ERROR_B_BIT_SET): - /* cc=2 and busy bit: */ - atomic_inc(&q->busy_siga_counter); - - /* if the last siga was successful, save - * timestamp here */ - if (!q->timing.busy_start) - q->timing.busy_start=NOW; - - /* if we're in time, don't touch error_status_flags - * and siga_error */ - if (NOW-q->timing.busy_starttiming.busy_start=0; break; - } - QDIO_DBF_TEXT2(0,trace,"cc2REPRT"); + case (2|QDIO_SIGA_ERROR_B_BIT_SET): + /* cc=2 and busy bit: */ + atomic_inc(&q->busy_siga_counter); + + /* if the last siga was successful, save + * timestamp here */ + if (!q->timing.busy_start) + q->timing.busy_start=NOW; + + /* if we're in time, don't touch error_status_flags + * and siga_error */ + if (NOW-q->timing.busy_startschid.sch_no,q->q_no, - atomic_read(&q->busy_siga_counter)); - QDIO_DBF_TEXT3(0,trace,dbf_text); + sprintf(dbf_text,"%4x%2x%2x",q->irq,q->q_no, + atomic_read(&q->busy_siga_counter)); + QDIO_DBF_TEXT3(0,trace,dbf_text); #endif /* CONFIG_QDIO_DEBUG */ - /* else fallthrough and report error */ - default: - /* for plain cc=1, 2 or 3: */ - if (q->siga_error) + /* else fallthrough and report error */ + default: + /* for plain cc=1, 2 or 3: */ + if (q->siga_error) + q->error_status_flags|= + QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR; q->error_status_flags|= - QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR; - q->error_status_flags|= - QDIO_STATUS_LOOK_FOR_ERROR; - q->siga_error=result; - } + QDIO_STATUS_LOOK_FOR_ERROR; + q->siga_error=result; + } } static inline void @@ -1000,10 +743,8 @@ qdio_outbound_processing(struct qdio_q *q) static inline int qdio_get_inbound_buffer_frontier(struct qdio_q *q) { - struct qdio_irq *irq; int f,f_mod_no; volatile char *slsb; - unsigned int count = 1; int first_not_to_check; #ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; @@ -1015,10 +756,6 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q) QDIO_DBF_TEXT4(0,trace,"getibfro"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - irq = (struct qdio_irq *) q->irq_ptr; - if (irq->is_qebsm) - return qdio_qebsm_get_inbound_buffer_frontier(q); - slsb=&q->slsb.acc.val[0]; f_mod_no=f=q->first_to_check; /* @@ -1055,19 +792,19 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q) * kill VM in terms of CP overhead */ if (q->siga_sync) { - set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count); + set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); } else { /* set the previous buffer to NOT_INIT. The current * buffer will be set to PROCESSING at the end of * this function to avoid further interrupts. */ if (last_position>=0) - set_slsb(q, &last_position, - SLSB_P_INPUT_NOT_INIT, &count); + set_slsb(&slsb[last_position], + SLSB_P_INPUT_NOT_INIT); atomic_set(&q->polling,1); last_position=f_mod_no; } #else /* QDIO_USE_PROCESSING_STATE */ - set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count); + set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); #endif /* QDIO_USE_PROCESSING_STATE */ /* * not needed, as the inbound queue will be synced on the next @@ -1092,7 +829,7 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q) QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256); /* kind of process the buffer */ - set_slsb(q, &f_mod_no, SLSB_P_INPUT_NOT_INIT, &count); + set_slsb(&slsb[f_mod_no],SLSB_P_INPUT_NOT_INIT); if (q->qdio_error) q->error_status_flags|= @@ -1120,7 +857,7 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q) #ifdef QDIO_USE_PROCESSING_STATE if (last_position>=0) - set_slsb(q, &last_position, SLSB_P_INPUT_NOT_INIT, &count); + set_slsb(&slsb[last_position],SLSB_P_INPUT_PROCESSING); #endif /* QDIO_USE_PROCESSING_STATE */ QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); @@ -1165,10 +902,6 @@ static inline int tiqdio_is_inbound_q_done(struct qdio_q *q) { int no_used; - unsigned int start_buf, count; - unsigned char state = 0; - struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; - #ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; #endif @@ -1194,13 +927,8 @@ tiqdio_is_inbound_q_done(struct qdio_q *q) if (!q->siga_sync) /* we'll check for more primed buffers in qeth_stop_polling */ return 0; - if (irq->is_qebsm) { - count = 1; - start_buf = q->first_to_check; - qdio_do_eqbs(q, &state, &start_buf, &count); - } else - state = q->slsb.acc.val[q->first_to_check]; - if (state != SLSB_P_INPUT_PRIMED) + + if (q->slsb.acc.val[q->first_to_check]!=SLSB_P_INPUT_PRIMED) /* * nothing more to do, if next buffer is not PRIMED. * note that we did a SYNC_MEMORY before, that there @@ -1227,10 +955,6 @@ static inline int qdio_is_inbound_q_done(struct qdio_q *q) { int no_used; - unsigned int start_buf, count; - unsigned char state = 0; - struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; - #ifdef CONFIG_QDIO_DEBUG char dbf_text[15]; #endif @@ -1249,13 +973,8 @@ qdio_is_inbound_q_done(struct qdio_q *q) QDIO_DBF_TEXT4(0,trace,dbf_text); return 1; } - if (irq->is_qebsm) { - count = 1; - start_buf = q->first_to_check; - qdio_do_eqbs(q, &state, &start_buf, &count); - } else - state = q->slsb.acc.val[q->first_to_check]; - if (state == SLSB_P_INPUT_PRIMED) { + + if (q->slsb.acc.val[q->first_to_check]==SLSB_P_INPUT_PRIMED) { /* we got something to do */ QDIO_DBF_TEXT4(0,trace,"inqisntA"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -1737,7 +1456,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, void *ptr; int available; - sprintf(dbf_text,"qfqs%4x",cdev->private->sch_no); + sprintf(dbf_text,"qfqs%4x",cdev->private->irq); QDIO_DBF_TEXT0(0,setup,dbf_text); for (i=0;iinput_qs[i]; @@ -1757,7 +1476,7 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, q->queue_type=q_format; q->int_parm=int_parm; - q->schid = irq_ptr->schid; + q->irq=irq_ptr->irq; q->irq_ptr = irq_ptr; q->cdev = cdev; q->mask=1<<(31-i); @@ -1804,11 +1523,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*)); /* fill in slsb */ - if (!irq_ptr->is_qebsm) { - unsigned int count = 1; - for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) - set_slsb(q, &j, SLSB_P_INPUT_NOT_INIT, &count); - } + for (j=0;jslsb.acc.val[j], + SLSB_P_INPUT_NOT_INIT); +/* q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/ + } } for (i=0;iqueue_type=q_format; q->int_parm=int_parm; q->is_input_q=0; - q->schid = irq_ptr->schid; + q->irq=irq_ptr->irq; q->cdev = cdev; q->irq_ptr = irq_ptr; q->mask=1<<(31-i); @@ -1865,11 +1584,11 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, QDIO_DBF_HEX2(0,setup,&ptr,sizeof(void*)); /* fill in slsb */ - if (!irq_ptr->is_qebsm) { - unsigned int count = 1; - for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) - set_slsb(q, &j, SLSB_P_OUTPUT_NOT_INIT, &count); - } + for (j=0;jslsb.acc.val[j], + SLSB_P_OUTPUT_NOT_INIT); +/* q->sbal[j]->element[1].sbalf.i1.key=QDIO_STORAGE_KEY;*/ + } } } @@ -1937,7 +1656,7 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state) char dbf_text[15]; QDIO_DBF_TEXT5(0,trace,"newstate"); - sprintf(dbf_text,"%4x%4x",irq_ptr->schid.sch_no,state); + sprintf(dbf_text,"%4x%4x",irq_ptr->irq,state); QDIO_DBF_TEXT5(0,trace,dbf_text); #endif /* CONFIG_QDIO_DEBUG */ @@ -1950,12 +1669,12 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state) } static inline void -qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb) +qdio_irq_check_sense(int irq, struct irb *irb) { char dbf_text[15]; if (irb->esw.esw0.erw.cons) { - sprintf(dbf_text,"sens%4x",schid.sch_no); + sprintf(dbf_text,"sens%4x",irq); QDIO_DBF_TEXT2(1,trace,dbf_text); QDIO_DBF_HEX0(0,sense,irb,QDIO_DBF_SENSE_LEN); @@ -2066,22 +1785,21 @@ qdio_timeout_handler(struct ccw_device *cdev) switch (irq_ptr->state) { case QDIO_IRQ_STATE_INACTIVE: - QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: timed out\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no); + QDIO_PRINT_ERR("establish queues on irq %04x: timed out\n", + irq_ptr->irq); QDIO_DBF_TEXT2(1,setup,"eq:timeo"); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); break; case QDIO_IRQ_STATE_CLEANUP: - QDIO_PRINT_INFO("Did not get interrupt on cleanup, " - "irq=0.%x.%x.\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no); + QDIO_PRINT_INFO("Did not get interrupt on cleanup, irq=0x%x.\n", + irq_ptr->irq); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); break; case QDIO_IRQ_STATE_ESTABLISHED: case QDIO_IRQ_STATE_ACTIVE: /* I/O has been terminated by common I/O layer. */ - QDIO_PRINT_INFO("Queues on irq 0.%x.%04x killed by cio.\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no); + QDIO_PRINT_INFO("Queues on irq %04x killed by cio.\n", + irq_ptr->irq); QDIO_DBF_TEXT2(1, trace, "cio:term"); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_STOPPED); if (get_device(&cdev->dev)) { @@ -2144,7 +1862,7 @@ qdio_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) } } - qdio_irq_check_sense(irq_ptr->schid, irb); + qdio_irq_check_sense(irq_ptr->irq, irb); #ifdef CONFIG_QDIO_DEBUG sprintf(dbf_text, "state:%d", irq_ptr->state); @@ -2187,7 +1905,7 @@ int qdio_synchronize(struct ccw_device *cdev, unsigned int flags, unsigned int queue_number) { - int cc = 0; + int cc; struct qdio_q *q; struct qdio_irq *irq_ptr; void *ptr; @@ -2200,7 +1918,7 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags, return -ENODEV; #ifdef CONFIG_QDIO_DEBUG - *((int*)(&dbf_text[4])) = irq_ptr->schid.sch_no; + *((int*)(&dbf_text[4])) = irq_ptr->irq; QDIO_DBF_HEX4(0,trace,dbf_text,QDIO_DBF_TRACE_LEN); *((int*)(&dbf_text[0]))=flags; *((int*)(&dbf_text[4]))=queue_number; @@ -2211,14 +1929,12 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags, q=irq_ptr->input_qs[queue_number]; if (!q) return -EINVAL; - if (!(irq_ptr->is_qebsm)) - cc = do_siga_sync(q->schid, 0, q->mask); + cc = do_siga_sync(q->irq, 0, q->mask); } else if (flags&QDIO_FLAG_SYNC_OUTPUT) { q=irq_ptr->output_qs[queue_number]; if (!q) return -EINVAL; - if (!(irq_ptr->is_qebsm)) - cc = do_siga_sync(q->schid, q->mask, 0); + cc = do_siga_sync(q->irq, q->mask, 0); } else return -EINVAL; @@ -2229,54 +1945,15 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags, return cc; } -static inline void -qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac, - unsigned long token) -{ - struct qdio_q *q; - int i; - unsigned int count, start_buf; - char dbf_text[15]; - - /*check if QEBSM is disabled */ - if (!(irq_ptr->is_qebsm) || !(qdioac & 0x01)) { - irq_ptr->is_qebsm = 0; - irq_ptr->sch_token = 0; - irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM; - QDIO_DBF_TEXT0(0,setup,"noV=V"); - return; - } - irq_ptr->sch_token = token; - /*input queue*/ - for (i = 0; i < irq_ptr->no_input_qs;i++) { - q = irq_ptr->input_qs[i]; - count = QDIO_MAX_BUFFERS_PER_Q; - start_buf = 0; - set_slsb(q, &start_buf, SLSB_P_INPUT_NOT_INIT, &count); - } - sprintf(dbf_text,"V=V:%2x",irq_ptr->is_qebsm); - QDIO_DBF_TEXT0(0,setup,dbf_text); - sprintf(dbf_text,"%8lx",irq_ptr->sch_token); - QDIO_DBF_TEXT0(0,setup,dbf_text); - /*output queue*/ - for (i = 0; i < irq_ptr->no_output_qs; i++) { - q = irq_ptr->output_qs[i]; - count = QDIO_MAX_BUFFERS_PER_Q; - start_buf = 0; - set_slsb(q, &start_buf, SLSB_P_OUTPUT_NOT_INIT, &count); - } -} - -static void -qdio_get_ssqd_information(struct qdio_irq *irq_ptr) +static unsigned char +qdio_check_siga_needs(int sch) { int result; unsigned char qdioac; + struct { struct chsc_header request; - u16 reserved1:10; - u16 ssid:2; - u16 fmt:4; + u16 reserved1; u16 first_sch; u16 reserved2; u16 last_sch; @@ -2287,83 +1964,67 @@ qdio_get_ssqd_information(struct qdio_irq *irq_ptr) u8 reserved5; u16 sch; u8 qfmt; - u8 parm; - u8 qdioac1; + u8 reserved6; + u8 qdioac; u8 sch_class; u8 reserved7; u8 icnt; u8 reserved8; u8 ocnt; - u8 reserved9; - u8 mbccnt; - u16 qdioac2; - u64 sch_token; } *ssqd_area; - QDIO_DBF_TEXT0(0,setup,"getssqd"); - qdioac = 0; ssqd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!ssqd_area) { QDIO_PRINT_WARN("Could not get memory for chsc. Using all " \ - "SIGAs for sch x%x.\n", irq_ptr->schid.sch_no); - irq_ptr->qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || - CHSC_FLAG_SIGA_OUTPUT_NECESSARY || - CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ - irq_ptr->is_qebsm = 0; - irq_ptr->sch_token = 0; - irq_ptr->qib.rflags &= ~QIB_RFLAGS_ENABLE_QEBSM; - return; + "SIGAs for sch x%x.\n", sch); + return CHSC_FLAG_SIGA_INPUT_NECESSARY || + CHSC_FLAG_SIGA_OUTPUT_NECESSARY || + CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ } - ssqd_area->request = (struct chsc_header) { .length = 0x0010, .code = 0x0024, }; - ssqd_area->first_sch = irq_ptr->schid.sch_no; - ssqd_area->last_sch = irq_ptr->schid.sch_no; - ssqd_area->ssid = irq_ptr->schid.ssid; - result = chsc(ssqd_area); + + ssqd_area->first_sch = sch; + ssqd_area->last_sch = sch; + + result=chsc(ssqd_area); if (result) { QDIO_PRINT_WARN("CHSC returned cc %i. Using all " \ - "SIGAs for sch 0.%x.%x.\n", result, - irq_ptr->schid.ssid, irq_ptr->schid.sch_no); + "SIGAs for sch x%x.\n", + result,sch); qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || CHSC_FLAG_SIGA_OUTPUT_NECESSARY || CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ - irq_ptr->is_qebsm = 0; goto out; } if (ssqd_area->response.code != QDIO_CHSC_RESPONSE_CODE_OK) { QDIO_PRINT_WARN("response upon checking SIGA needs " \ - "is 0x%x. Using all SIGAs for sch 0.%x.%x.\n", - ssqd_area->response.code, - irq_ptr->schid.ssid, irq_ptr->schid.sch_no); + "is 0x%x. Using all SIGAs for sch x%x.\n", + ssqd_area->response.code, sch); qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY || CHSC_FLAG_SIGA_OUTPUT_NECESSARY || CHSC_FLAG_SIGA_SYNC_NECESSARY; /* all flags set */ - irq_ptr->is_qebsm = 0; goto out; } if (!(ssqd_area->flags & CHSC_FLAG_QDIO_CAPABILITY) || !(ssqd_area->flags & CHSC_FLAG_VALIDITY) || - (ssqd_area->sch != irq_ptr->schid.sch_no)) { - QDIO_PRINT_WARN("huh? problems checking out sch 0.%x.%x... " \ - "using all SIGAs.\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no); + (ssqd_area->sch != sch)) { + QDIO_PRINT_WARN("huh? problems checking out sch x%x... " \ + "using all SIGAs.\n",sch); qdioac = CHSC_FLAG_SIGA_INPUT_NECESSARY | CHSC_FLAG_SIGA_OUTPUT_NECESSARY | CHSC_FLAG_SIGA_SYNC_NECESSARY; /* worst case */ - irq_ptr->is_qebsm = 0; goto out; } - qdioac = ssqd_area->qdioac1; + + qdioac = ssqd_area->qdioac; out: - qdio_check_subchannel_qebsm(irq_ptr, qdioac, - ssqd_area->sch_token); free_page ((unsigned long) ssqd_area); - irq_ptr->qdioac = qdioac; + return qdioac; } static unsigned int @@ -2394,13 +2055,6 @@ tiqdio_check_chsc_availability(void) sprintf(dbf_text,"hydrati%1x", hydra_thinints); QDIO_DBF_TEXT0(0,setup,dbf_text); -#ifdef CONFIG_64BIT - /* Check for QEBSM support in general (bit 58). */ - is_passthrough = css_general_characteristics.qebsm; -#endif - sprintf(dbf_text,"cssQBS:%1x", is_passthrough); - QDIO_DBF_TEXT0(0,setup,dbf_text); - /* Check for aif time delay disablement fac (bit 56). If installed, * omit svs even under lpar (good point by rick again) */ omit_svs = css_general_characteristics.aif_tdd; @@ -2437,7 +2091,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) /* set to 0x10000000 to enable * time delay disablement facility */ u32 reserved5; - struct subchannel_id schid; + u32 subsystem_id; u32 reserved6[1004]; struct chsc_header response; u32 reserved7; @@ -2459,8 +2113,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) scssc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!scssc_area) { QDIO_PRINT_WARN("No memory for setting indicators on " \ - "subchannel 0.%x.%x.\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no); + "subchannel x%x.\n", irq_ptr->irq); return -ENOMEM; } scssc_area->request = (struct chsc_header) { @@ -2474,7 +2127,7 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) scssc_area->ks = QDIO_STORAGE_KEY; scssc_area->kc = QDIO_STORAGE_KEY; scssc_area->isc = TIQDIO_THININT_ISC; - scssc_area->schid = irq_ptr->schid; + scssc_area->subsystem_id = (1<<16) + irq_ptr->irq; /* enables the time delay disablement facility. Don't care * whether it is really there (i.e. we haven't checked for * it) */ @@ -2484,11 +2137,12 @@ tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) QDIO_PRINT_WARN("Time delay disablement facility " \ "not available\n"); + + result = chsc(scssc_area); if (result) { - QDIO_PRINT_WARN("could not set indicators on irq 0.%x.%x, " \ - "cc=%i.\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no,result); + QDIO_PRINT_WARN("could not set indicators on irq x%x, " \ + "cc=%i.\n",irq_ptr->irq,result); result = -EIO; goto out; } @@ -2544,8 +2198,7 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); if (!scsscf_area) { QDIO_PRINT_WARN("No memory for setting delay target on " \ - "subchannel 0.%x.%x.\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no); + "subchannel x%x.\n", irq_ptr->irq); return -ENOMEM; } scsscf_area->request = (struct chsc_header) { @@ -2557,10 +2210,8 @@ tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) result=chsc(scsscf_area); if (result) { - QDIO_PRINT_WARN("could not set delay target on irq 0.%x.%x, " \ - "cc=%i. Continuing.\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no, - result); + QDIO_PRINT_WARN("could not set delay target on irq x%x, " \ + "cc=%i. Continuing.\n",irq_ptr->irq,result); result = -EIO; goto out; } @@ -2594,7 +2245,7 @@ qdio_cleanup(struct ccw_device *cdev, int how) if (!irq_ptr) return -ENODEV; - sprintf(dbf_text,"qcln%4x",irq_ptr->schid.sch_no); + sprintf(dbf_text,"qcln%4x",irq_ptr->irq); QDIO_DBF_TEXT1(0,trace,dbf_text); QDIO_DBF_TEXT0(0,setup,dbf_text); @@ -2621,7 +2272,7 @@ qdio_shutdown(struct ccw_device *cdev, int how) down(&irq_ptr->setting_up_sema); - sprintf(dbf_text,"qsqs%4x",irq_ptr->schid.sch_no); + sprintf(dbf_text,"qsqs%4x",irq_ptr->irq); QDIO_DBF_TEXT1(0,trace,dbf_text); QDIO_DBF_TEXT0(0,setup,dbf_text); @@ -2727,7 +2378,7 @@ qdio_free(struct ccw_device *cdev) down(&irq_ptr->setting_up_sema); - sprintf(dbf_text,"qfqs%4x",irq_ptr->schid.sch_no); + sprintf(dbf_text,"qfqs%4x",irq_ptr->irq); QDIO_DBF_TEXT1(0,trace,dbf_text); QDIO_DBF_TEXT0(0,setup,dbf_text); @@ -2875,14 +2526,13 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat, irq_ptr = cdev->private->qdio_data; if (cstat || (dstat & ~(DEV_STAT_CHN_END|DEV_STAT_DEV_END))) { - sprintf(dbf_text,"ick1%4x",irq_ptr->schid.sch_no); + sprintf(dbf_text,"ick1%4x",irq_ptr->irq); QDIO_DBF_TEXT2(1,trace,dbf_text); QDIO_DBF_HEX2(0,trace,&dstat,sizeof(int)); QDIO_DBF_HEX2(0,trace,&cstat,sizeof(int)); QDIO_PRINT_ERR("received check condition on establish " \ - "queues on irq 0.%x.%x (cs=x%x, ds=x%x).\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no, - cstat,dstat); + "queues on irq 0x%x (cs=x%x, ds=x%x).\n", + irq_ptr->irq,cstat,dstat); qdio_set_state(irq_ptr,QDIO_IRQ_STATE_ERR); } @@ -2890,10 +2540,9 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat, QDIO_DBF_TEXT2(1,setup,"eq:no de"); QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); - QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: didn't get " + QDIO_PRINT_ERR("establish queues on irq %04x: didn't get " "device end: dstat=%02x, cstat=%02x\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no, - dstat, cstat); + irq_ptr->irq, dstat, cstat); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); return 1; } @@ -2902,10 +2551,10 @@ qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat, QDIO_DBF_TEXT2(1,setup,"eq:badio"); QDIO_DBF_HEX2(0,setup,&dstat, sizeof(dstat)); QDIO_DBF_HEX2(0,setup,&cstat, sizeof(cstat)); - QDIO_PRINT_ERR("establish queues on irq 0.%x.%04x: got " + QDIO_PRINT_ERR("establish queues on irq %04x: got " "the following devstat: dstat=%02x, " - "cstat=%02x\n", irq_ptr->schid.ssid, - irq_ptr->schid.sch_no, dstat, cstat); + "cstat=%02x\n", + irq_ptr->irq, dstat, cstat); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); return 1; } @@ -2920,7 +2569,7 @@ qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, int dstat) irq_ptr = cdev->private->qdio_data; - sprintf(dbf_text,"qehi%4x",cdev->private->sch_no); + sprintf(dbf_text,"qehi%4x",cdev->private->irq); QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); @@ -2939,7 +2588,7 @@ qdio_initialize(struct qdio_initialize *init_data) int rc; char dbf_text[15]; - sprintf(dbf_text,"qini%4x",init_data->cdev->private->sch_no); + sprintf(dbf_text,"qini%4x",init_data->cdev->private->irq); QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); @@ -2960,7 +2609,7 @@ qdio_allocate(struct qdio_initialize *init_data) struct qdio_irq *irq_ptr; char dbf_text[15]; - sprintf(dbf_text,"qalc%4x",init_data->cdev->private->sch_no); + sprintf(dbf_text,"qalc%4x",init_data->cdev->private->irq); QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) || @@ -3033,7 +2682,7 @@ int qdio_fill_irq(struct qdio_initialize *init_data) irq_ptr->int_parm=init_data->int_parm; - irq_ptr->schid = ccw_device_get_subchannel_id(init_data->cdev); + irq_ptr->irq = init_data->cdev->private->irq; irq_ptr->no_input_qs=init_data->no_input_qs; irq_ptr->no_output_qs=init_data->no_output_qs; @@ -3049,12 +2698,11 @@ int qdio_fill_irq(struct qdio_initialize *init_data) QDIO_DBF_TEXT2(0,setup,dbf_text); if (irq_ptr->is_thinint_irq) { - irq_ptr->dev_st_chg_ind = qdio_get_indicator(); + irq_ptr->dev_st_chg_ind=qdio_get_indicator(); QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*)); if (!irq_ptr->dev_st_chg_ind) { QDIO_PRINT_WARN("no indicator location available " \ - "for irq 0.%x.%x\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no); + "for irq 0x%x\n",irq_ptr->irq); qdio_release_irq_memory(irq_ptr); return -ENOBUFS; } @@ -3099,10 +2747,6 @@ int qdio_fill_irq(struct qdio_initialize *init_data) irq_ptr->qdr->qkey=QDIO_STORAGE_KEY; /* fill in qib */ - irq_ptr->is_qebsm = is_passthrough; - if (irq_ptr->is_qebsm) - irq_ptr->qib.rflags |= QIB_RFLAGS_ENABLE_QEBSM; - irq_ptr->qib.qfmt=init_data->q_format; if (init_data->no_input_qs) irq_ptr->qib.isliba=(unsigned long)(irq_ptr->input_qs[0]->slib); @@ -3185,7 +2829,7 @@ qdio_establish(struct qdio_initialize *init_data) tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET); } - sprintf(dbf_text,"qest%4x",cdev->private->sch_no); + sprintf(dbf_text,"qest%4x",cdev->private->irq); QDIO_DBF_TEXT0(0,setup,dbf_text); QDIO_DBF_TEXT0(0,trace,dbf_text); @@ -3211,10 +2855,9 @@ qdio_establish(struct qdio_initialize *init_data) sprintf(dbf_text,"eq:io%4x",result); QDIO_DBF_TEXT2(1,setup,dbf_text); } - QDIO_PRINT_WARN("establish queues on irq 0.%x.%04x: do_IO " \ - "returned %i, next try returned %i\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no, - result, result2); + QDIO_PRINT_WARN("establish queues on irq %04x: do_IO " \ + "returned %i, next try returned %i\n", + irq_ptr->irq,result,result2); result=result2; if (result) ccw_device_set_timeout(cdev, 0); @@ -3241,7 +2884,7 @@ qdio_establish(struct qdio_initialize *init_data) return -EIO; } - qdio_get_ssqd_information(irq_ptr); + irq_ptr->qdioac=qdio_check_siga_needs(irq_ptr->irq); /* if this gets set once, we're running under VM and can omit SVSes */ if (irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_NECESSARY) omit_svs=1; @@ -3287,7 +2930,7 @@ qdio_activate(struct ccw_device *cdev, int flags) goto out; } - sprintf(dbf_text,"qact%4x", irq_ptr->schid.sch_no); + sprintf(dbf_text,"qact%4x", irq_ptr->irq); QDIO_DBF_TEXT2(0,setup,dbf_text); QDIO_DBF_TEXT2(0,trace,dbf_text); @@ -3312,10 +2955,9 @@ qdio_activate(struct ccw_device *cdev, int flags) sprintf(dbf_text,"aq:io%4x",result); QDIO_DBF_TEXT2(1,setup,dbf_text); } - QDIO_PRINT_WARN("activate queues on irq 0.%x.%04x: do_IO " \ - "returned %i, next try returned %i\n", - irq_ptr->schid.ssid, irq_ptr->schid.sch_no, - result, result2); + QDIO_PRINT_WARN("activate queues on irq %04x: do_IO " \ + "returned %i, next try returned %i\n", + irq_ptr->irq,result,result2); result=result2; } @@ -3373,40 +3015,30 @@ static inline void qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, unsigned int count, struct qdio_buffer *buffers) { - struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; - qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1); - if (irq->is_qebsm) { - while (count) - set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count); - return; - } for (;;) { - set_slsb(q, &qidx, SLSB_CU_INPUT_EMPTY, &count); + set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_INPUT_EMPTY); count--; if (!count) break; - qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1); + qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1); } + + /* not necessary, as the queues are synced during the SIGA read */ + /*SYNC_MEMORY;*/ } static inline void qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx, unsigned int count, struct qdio_buffer *buffers) { - struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; - - qidx &= (QDIO_MAX_BUFFERS_PER_Q - 1); - if (irq->is_qebsm) { - while (count) - set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count); - return; - } - for (;;) { - set_slsb(q, &qidx, SLSB_CU_OUTPUT_PRIMED, &count); + set_slsb(&q->slsb.acc.val[qidx],SLSB_CU_OUTPUT_PRIMED); count--; if (!count) break; - qidx = (qidx + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1); + qidx=(qidx+1)&(QDIO_MAX_BUFFERS_PER_Q-1); } + + /* SIGA write will sync the queues */ + /*SYNC_MEMORY;*/ } static inline void @@ -3451,9 +3083,6 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, struct qdio_buffer *buffers) { int used_elements; - unsigned int cnt, start_buf; - unsigned char state = 0; - struct qdio_irq *irq = (struct qdio_irq *) q->irq_ptr; /* This is the outbound handling of queues */ #ifdef QDIO_PERFORMANCE_STATS @@ -3486,15 +3115,9 @@ do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, * SYNC_MEMORY :-/ ), we try to * fast-requeue buffers */ - if (irq->is_qebsm) { - cnt = 1; - start_buf = ((qidx+QDIO_MAX_BUFFERS_PER_Q-1) & - (QDIO_MAX_BUFFERS_PER_Q-1)); - qdio_do_eqbs(q, &state, &start_buf, &cnt); - } else - state = q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1) - &(QDIO_MAX_BUFFERS_PER_Q-1) ]; - if (state != SLSB_CU_OUTPUT_PRIMED) { + if (q->slsb.acc.val[(qidx+QDIO_MAX_BUFFERS_PER_Q-1) + &(QDIO_MAX_BUFFERS_PER_Q-1)]!= + SLSB_CU_OUTPUT_PRIMED) { qdio_kick_outbound_q(q); } else { QDIO_DBF_TEXT3(0,trace, "fast-req"); @@ -3527,7 +3150,7 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags, #ifdef CONFIG_QDIO_DEBUG char dbf_text[20]; - sprintf(dbf_text,"doQD%04x",cdev->private->sch_no); + sprintf(dbf_text,"doQD%04x",cdev->private->irq); QDIO_DBF_TEXT3(0,trace,dbf_text); #endif /* CONFIG_QDIO_DEBUG */ diff --git a/trunk/drivers/s390/cio/qdio.h b/trunk/drivers/s390/cio/qdio.h index fa385e761fe1..328e31cc6854 100644 --- a/trunk/drivers/s390/cio/qdio.h +++ b/trunk/drivers/s390/cio/qdio.h @@ -3,15 +3,14 @@ #include -#include "schid.h" - -#define VERSION_CIO_QDIO_H "$Revision: 1.40 $" +#define VERSION_CIO_QDIO_H "$Revision: 1.33 $" #ifdef CONFIG_QDIO_DEBUG #define QDIO_VERBOSE_LEVEL 9 #else /* CONFIG_QDIO_DEBUG */ #define QDIO_VERBOSE_LEVEL 5 #endif /* CONFIG_QDIO_DEBUG */ + #define QDIO_USE_PROCESSING_STATE #ifdef CONFIG_QDIO_PERF_STATS @@ -266,64 +265,12 @@ QDIO_PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \ /* * Some instructions as assembly */ - -static inline int -do_sqbs(unsigned long sch, unsigned char state, int queue, - unsigned int *start, unsigned int *count) -{ -#ifdef CONFIG_64BIT - register unsigned long _ccq asm ("0") = *count; - register unsigned long _sch asm ("1") = sch; - unsigned long _queuestart = ((unsigned long)queue << 32) | *start; - - asm volatile ( - " .insn rsy,0xeb000000008A,%1,0,0(%2)\n\t" - : "+d" (_ccq), "+d" (_queuestart) - : "d" ((unsigned long)state), "d" (_sch) - : "memory", "cc" - ); - *count = _ccq & 0xff; - *start = _queuestart & 0xff; - - return (_ccq >> 32) & 0xff; -#else - return 0; -#endif -} - -static inline int -do_eqbs(unsigned long sch, unsigned char *state, int queue, - unsigned int *start, unsigned int *count) -{ -#ifdef CONFIG_64BIT - register unsigned long _ccq asm ("0") = *count; - register unsigned long _sch asm ("1") = sch; - unsigned long _queuestart = ((unsigned long)queue << 32) | *start; - unsigned long _state = 0; - - asm volatile ( - " .insn rrf,0xB99c0000,%1,%2,0,0 \n\t" - : "+d" (_ccq), "+d" (_queuestart), "+d" (_state) - : "d" (_sch) - : "memory", "cc" - ); - *count = _ccq & 0xff; - *start = _queuestart & 0xff; - *state = _state & 0xff; - - return (_ccq >> 32) & 0xff; -#else - return 0; -#endif -} - - static inline int -do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2) +do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2) { int cc; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X asm volatile ( "lhi 0,2 \n\t" "lr 1,%1 \n\t" @@ -333,10 +280,10 @@ do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2) "ipm %0 \n\t" "srl %0,28 \n\t" : "=d" (cc) - : "d" (schid), "d" (mask1), "d" (mask2) + : "d" (0x10000|irq), "d" (mask1), "d" (mask2) : "cc", "0", "1", "2", "3" ); -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ asm volatile ( "lghi 0,2 \n\t" "llgfr 1,%1 \n\t" @@ -346,19 +293,19 @@ do_siga_sync(struct subchannel_id schid, unsigned int mask1, unsigned int mask2) "ipm %0 \n\t" "srl %0,28 \n\t" : "=d" (cc) - : "d" (schid), "d" (mask1), "d" (mask2) + : "d" (0x10000|irq), "d" (mask1), "d" (mask2) : "cc", "0", "1", "2", "3" ); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ return cc; } static inline int -do_siga_input(struct subchannel_id schid, unsigned int mask) +do_siga_input(unsigned int irq, unsigned int mask) { int cc; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X asm volatile ( "lhi 0,1 \n\t" "lr 1,%1 \n\t" @@ -367,10 +314,10 @@ do_siga_input(struct subchannel_id schid, unsigned int mask) "ipm %0 \n\t" "srl %0,28 \n\t" : "=d" (cc) - : "d" (schid), "d" (mask) + : "d" (0x10000|irq), "d" (mask) : "cc", "0", "1", "2", "memory" ); -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ asm volatile ( "lghi 0,1 \n\t" "llgfr 1,%1 \n\t" @@ -379,22 +326,21 @@ do_siga_input(struct subchannel_id schid, unsigned int mask) "ipm %0 \n\t" "srl %0,28 \n\t" : "=d" (cc) - : "d" (schid), "d" (mask) + : "d" (0x10000|irq), "d" (mask) : "cc", "0", "1", "2", "memory" ); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ return cc; } static inline int -do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb, - unsigned int fc) +do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb) { int cc; __u32 busy_bit; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X asm volatile ( "lhi 0,0 \n\t" "lr 1,%2 \n\t" @@ -420,14 +366,14 @@ do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb, ".long 0b,2b \n\t" ".previous \n\t" : "=d" (cc), "=d" (busy_bit) - : "d" (schid), "d" (mask), + : "d" (0x10000|irq), "d" (mask), "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION) : "cc", "0", "1", "2", "memory" ); -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ asm volatile ( - "llgfr 0,%5 \n\t" - "lgr 1,%2 \n\t" + "lghi 0,0 \n\t" + "llgfr 1,%2 \n\t" "llgfr 2,%3 \n\t" "siga 0 \n\t" "0:" @@ -445,11 +391,11 @@ do_siga_output(unsigned long schid, unsigned long mask, __u32 *bb, ".quad 0b,1b \n\t" ".previous \n\t" : "=d" (cc), "=d" (busy_bit) - : "d" (schid), "d" (mask), - "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION), "d" (fc) + : "d" (0x10000|irq), "d" (mask), + "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION) : "cc", "0", "1", "2", "memory" ); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ (*bb) = busy_bit; return cc; @@ -461,21 +407,21 @@ do_clear_global_summary(void) unsigned long time; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X asm volatile ( "lhi 1,3 \n\t" ".insn rre,0xb2650000,2,0 \n\t" "lr %0,3 \n\t" : "=d" (time) : : "cc", "1", "2", "3" ); -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ asm volatile ( "lghi 1,3 \n\t" ".insn rre,0xb2650000,2,0 \n\t" "lgr %0,3 \n\t" : "=d" (time) : : "cc", "1", "2", "3" ); -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ return time; } @@ -542,21 +488,42 @@ struct qdio_perf_stats { #define MY_MODULE_STRING(x) #x -#ifdef CONFIG_64BIT +#ifdef CONFIG_ARCH_S390X #define QDIO_GET_ADDR(x) ((__u32)(unsigned long)x) -#else /* CONFIG_64BIT */ +#else /* CONFIG_ARCH_S390X */ #define QDIO_GET_ADDR(x) ((__u32)(long)x) -#endif /* CONFIG_64BIT */ +#endif /* CONFIG_ARCH_S390X */ + +#ifdef CONFIG_QDIO_DEBUG +#define set_slsb(x,y) \ + if(q->queue_type==QDIO_TRACE_QTYPE) { \ + if(q->is_input_q) { \ + QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \ + } else { \ + QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \ + } \ + } \ + qdio_set_slsb(x,y); \ + if(q->queue_type==QDIO_TRACE_QTYPE) { \ + if(q->is_input_q) { \ + QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \ + } else { \ + QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \ + } \ + } +#else /* CONFIG_QDIO_DEBUG */ +#define set_slsb(x,y) qdio_set_slsb(x,y) +#endif /* CONFIG_QDIO_DEBUG */ struct qdio_q { volatile struct slsb slsb; char unused[QDIO_MAX_BUFFERS_PER_Q]; - __u32 * dev_st_chg_ind; + __u32 * volatile dev_st_chg_ind; int is_input_q; - struct subchannel_id schid; + int irq; struct ccw_device *cdev; unsigned int is_iqdio_q; @@ -601,7 +568,6 @@ struct qdio_q { struct tasklet_struct tasklet; #endif /* QDIO_USE_TIMERS_FOR_POLLING */ - enum qdio_irq_states state; /* used to store the error condition during a data transfer */ @@ -651,17 +617,13 @@ struct qdio_irq { __u32 * volatile dev_st_chg_ind; unsigned long int_parm; - struct subchannel_id schid; + int irq; unsigned int is_iqdio_irq; unsigned int is_thinint_irq; unsigned int hydra_gives_outbound_pcis; unsigned int sync_done_on_outb_pcis; - /* QEBSM facility */ - unsigned int is_qebsm; - unsigned long sch_token; - enum qdio_irq_states state; unsigned int no_input_qs; diff --git a/trunk/drivers/s390/cio/schid.h b/trunk/drivers/s390/cio/schid.h deleted file mode 100644 index 54328fec5ade..000000000000 --- a/trunk/drivers/s390/cio/schid.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef S390_SCHID_H -#define S390_SCHID_H - -struct subchannel_id { - __u32 reserved:13; - __u32 ssid:2; - __u32 one:1; - __u32 sch_no:16; -} __attribute__ ((packed,aligned(4))); - - -/* Helper function for sane state of pre-allocated subchannel_id. */ -static inline void -init_subchannel_id(struct subchannel_id *schid) -{ - memset(schid, 0, sizeof(struct subchannel_id)); - schid->one = 1; -} - -static inline int -schid_equal(struct subchannel_id *schid1, struct subchannel_id *schid2) -{ - return !memcmp(schid1, schid2, sizeof(struct subchannel_id)); -} - -#endif /* S390_SCHID_H */ diff --git a/trunk/drivers/s390/crypto/z90common.h b/trunk/drivers/s390/crypto/z90common.h index f87c785f2039..e319e78b5ea2 100644 --- a/trunk/drivers/s390/crypto/z90common.h +++ b/trunk/drivers/s390/crypto/z90common.h @@ -1,9 +1,9 @@ /* * linux/drivers/s390/crypto/z90common.h * - * z90crypt 1.3.3 + * z90crypt 1.3.2 * - * Copyright (C) 2001, 2005 IBM Corporation + * Copyright (C) 2001, 2004 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) * Eric Rossman (edrossma@us.ibm.com) * @@ -91,13 +91,12 @@ enum hdstat { #define TSQ_FATAL_ERROR 34 #define RSQ_FATAL_ERROR 35 -#define Z90CRYPT_NUM_TYPES 6 +#define Z90CRYPT_NUM_TYPES 5 #define PCICA 0 #define PCICC 1 #define PCIXCC_MCL2 2 #define PCIXCC_MCL3 3 #define CEX2C 4 -#define CEX2A 5 #define NILDEV -1 #define ANYDEV -1 #define PCIXCC_UNK -2 @@ -106,7 +105,7 @@ enum hdevice_type { PCICC_HW = 3, PCICA_HW = 4, PCIXCC_HW = 5, - CEX2A_HW = 6, + OTHER_HW = 6, CEX2C_HW = 7 }; diff --git a/trunk/drivers/s390/crypto/z90crypt.h b/trunk/drivers/s390/crypto/z90crypt.h index 3a18443fdfa7..0a3bb5a10dd4 100644 --- a/trunk/drivers/s390/crypto/z90crypt.h +++ b/trunk/drivers/s390/crypto/z90crypt.h @@ -1,9 +1,9 @@ /* * linux/drivers/s390/crypto/z90crypt.h * - * z90crypt 1.3.3 + * z90crypt 1.3.2 * - * Copyright (C) 2001, 2005 IBM Corporation + * Copyright (C) 2001, 2004 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) * Eric Rossman (edrossma@us.ibm.com) * @@ -29,11 +29,11 @@ #include -#define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $" +#define VERSION_Z90CRYPT_H "$Revision: 1.11 $" #define z90crypt_VERSION 1 #define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards -#define z90crypt_VARIANT 3 // 3 = CEX2A support +#define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support /** * struct ica_rsa_modexpo @@ -122,9 +122,6 @@ struct ica_rsa_modexpo_crt { * Z90STAT_CEX2CCOUNT * Return an integer count of all CEX2Cs. * - * Z90STAT_CEX2ACOUNT - * Return an integer count of all CEX2As. - * * Z90STAT_REQUESTQ_COUNT * Return an integer count of the number of entries waiting to be * sent to a device. @@ -147,7 +144,6 @@ struct ica_rsa_modexpo_crt { * 0x03: PCIXCC_MCL2 * 0x04: PCIXCC_MCL3 * 0x05: CEX2C - * 0x06: CEX2A * 0x0d: device is disabled via the proc filesystem * * Z90STAT_QDEPTH_MASK @@ -203,7 +199,6 @@ struct ica_rsa_modexpo_crt { #define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int) #define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int) #define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int) -#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int) #define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int) #define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int) #define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int) diff --git a/trunk/drivers/s390/crypto/z90hardware.c b/trunk/drivers/s390/crypto/z90hardware.c index d7f7494a0cbe..c215e0889736 100644 --- a/trunk/drivers/s390/crypto/z90hardware.c +++ b/trunk/drivers/s390/crypto/z90hardware.c @@ -1,9 +1,9 @@ /* * linux/drivers/s390/crypto/z90hardware.c * - * z90crypt 1.3.3 + * z90crypt 1.3.2 * - * Copyright (C) 2001, 2005 IBM Corporation + * Copyright (C) 2001, 2004 IBM Corporation * Author(s): Robert Burroughs (burrough@us.ibm.com) * Eric Rossman (edrossma@us.ibm.com) * @@ -648,87 +648,6 @@ static struct cca_public_sec static_cca_pub_sec = { #define RESPONSE_CPRB_SIZE 0x000006B8 #define RESPONSE_CPRBX_SIZE 0x00000724 -struct type50_hdr { - u8 reserved1; - u8 msg_type_code; - u16 msg_len; - u8 reserved2; - u8 ignored; - u16 reserved3; -}; - -#define TYPE50_TYPE_CODE 0x50 - -#define TYPE50_MEB1_LEN (sizeof(struct type50_meb1_msg)) -#define TYPE50_MEB2_LEN (sizeof(struct type50_meb2_msg)) -#define TYPE50_CRB1_LEN (sizeof(struct type50_crb1_msg)) -#define TYPE50_CRB2_LEN (sizeof(struct type50_crb2_msg)) - -#define TYPE50_MEB1_FMT 0x0001 -#define TYPE50_MEB2_FMT 0x0002 -#define TYPE50_CRB1_FMT 0x0011 -#define TYPE50_CRB2_FMT 0x0012 - -struct type50_meb1_msg { - struct type50_hdr header; - u16 keyblock_type; - u8 reserved[6]; - u8 exponent[128]; - u8 modulus[128]; - u8 message[128]; -}; - -struct type50_meb2_msg { - struct type50_hdr header; - u16 keyblock_type; - u8 reserved[6]; - u8 exponent[256]; - u8 modulus[256]; - u8 message[256]; -}; - -struct type50_crb1_msg { - struct type50_hdr header; - u16 keyblock_type; - u8 reserved[6]; - u8 p[64]; - u8 q[64]; - u8 dp[64]; - u8 dq[64]; - u8 u[64]; - u8 message[128]; -}; - -struct type50_crb2_msg { - struct type50_hdr header; - u16 keyblock_type; - u8 reserved[6]; - u8 p[128]; - u8 q[128]; - u8 dp[128]; - u8 dq[128]; - u8 u[128]; - u8 message[256]; -}; - -union type50_msg { - struct type50_meb1_msg meb1; - struct type50_meb2_msg meb2; - struct type50_crb1_msg crb1; - struct type50_crb2_msg crb2; -}; - -struct type80_hdr { - u8 reserved1; - u8 type; - u16 len; - u8 code; - u8 reserved2[3]; - u8 reserved3[8]; -}; - -#define TYPE80_RSP_CODE 0x80 - struct error_hdr { unsigned char reserved1; unsigned char type; @@ -738,7 +657,6 @@ struct error_hdr { }; #define TYPE82_RSP_CODE 0x82 -#define TYPE88_RSP_CODE 0x88 #define REP82_ERROR_MACHINE_FAILURE 0x10 #define REP82_ERROR_PREEMPT_FAILURE 0x12 @@ -761,22 +679,6 @@ struct error_hdr { #define REP82_ERROR_PACKET_TRUNCATED 0xA0 #define REP82_ERROR_ZERO_BUFFER_LEN 0xB0 -#define REP88_ERROR_MODULE_FAILURE 0x10 -#define REP88_ERROR_MODULE_TIMEOUT 0x11 -#define REP88_ERROR_MODULE_NOTINIT 0x13 -#define REP88_ERROR_MODULE_NOTAVAIL 0x14 -#define REP88_ERROR_MODULE_DISABLED 0x15 -#define REP88_ERROR_MODULE_IN_DIAGN 0x17 -#define REP88_ERROR_FASTPATH_DISABLD 0x19 -#define REP88_ERROR_MESSAGE_TYPE 0x20 -#define REP88_ERROR_MESSAGE_MALFORMD 0x22 -#define REP88_ERROR_MESSAGE_LENGTH 0x23 -#define REP88_ERROR_RESERVED_FIELD 0x24 -#define REP88_ERROR_KEY_TYPE 0x34 -#define REP88_ERROR_INVALID_KEY 0x82 -#define REP88_ERROR_OPERAND 0x84 -#define REP88_ERROR_OPERAND_EVEN_MOD 0x85 - #define CALLER_HEADER 12 static inline int @@ -785,7 +687,7 @@ testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat) int ccode; asm volatile -#ifdef CONFIG_64BIT +#ifdef __s390x__ (" llgfr 0,%4 \n" " slgr 1,1 \n" " lgr 2,1 \n" @@ -855,7 +757,7 @@ resetq(int q_nr, struct ap_status_word *stat_p) int ccode; asm volatile -#ifdef CONFIG_64BIT +#ifdef __s390x__ (" llgfr 0,%2 \n" " lghi 1,1 \n" " sll 1,24 \n" @@ -921,7 +823,7 @@ sen(int msg_len, unsigned char *msg_ext, struct ap_status_word *stat) int ccode; asm volatile -#ifdef CONFIG_64BIT +#ifdef __s390x__ (" lgr 6,%3 \n" " llgfr 7,%2 \n" " llgt 0,0(6) \n" @@ -1000,7 +902,7 @@ rec(int q_nr, int buff_l, unsigned char *rsp, unsigned char *id, int ccode; asm volatile -#ifdef CONFIG_64BIT +#ifdef __s390x__ (" llgfr 0,%2 \n" " lgr 3,%4 \n" " lgr 6,%3 \n" @@ -1127,6 +1029,10 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) stat = HD_ONLINE; *q_depth = t_depth + 1; switch (t_dev_type) { + case OTHER_HW: + stat = HD_NOT_THERE; + *dev_type = NILDEV; + break; case PCICA_HW: *dev_type = PCICA; break; @@ -1139,9 +1045,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) case CEX2C_HW: *dev_type = CEX2C; break; - case CEX2A_HW: - *dev_type = CEX2A; - break; default: *dev_type = NILDEV; break; @@ -2126,177 +2029,6 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, return 0; } -static int -ICAMEX_msg_to_type50MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p, - union type50_msg *z90cMsg_p) -{ - int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len; - unsigned char *mod_tgt, *exp_tgt, *inp_tgt; - union type50_msg *tmp_type50_msg; - - mod_len = icaMex_p->inputdatalength; - - msg_size = ((mod_len <= 128) ? TYPE50_MEB1_LEN : TYPE50_MEB2_LEN) + - CALLER_HEADER; - - memset(z90cMsg_p, 0, msg_size); - - tmp_type50_msg = (union type50_msg *) - ((unsigned char *) z90cMsg_p + CALLER_HEADER); - - tmp_type50_msg->meb1.header.msg_type_code = TYPE50_TYPE_CODE; - - if (mod_len <= 128) { - tmp_type50_msg->meb1.header.msg_len = TYPE50_MEB1_LEN; - tmp_type50_msg->meb1.keyblock_type = TYPE50_MEB1_FMT; - mod_tgt = tmp_type50_msg->meb1.modulus; - mod_tgt_len = sizeof(tmp_type50_msg->meb1.modulus); - exp_tgt = tmp_type50_msg->meb1.exponent; - exp_tgt_len = sizeof(tmp_type50_msg->meb1.exponent); - inp_tgt = tmp_type50_msg->meb1.message; - inp_tgt_len = sizeof(tmp_type50_msg->meb1.message); - } else { - tmp_type50_msg->meb2.header.msg_len = TYPE50_MEB2_LEN; - tmp_type50_msg->meb2.keyblock_type = TYPE50_MEB2_FMT; - mod_tgt = tmp_type50_msg->meb2.modulus; - mod_tgt_len = sizeof(tmp_type50_msg->meb2.modulus); - exp_tgt = tmp_type50_msg->meb2.exponent; - exp_tgt_len = sizeof(tmp_type50_msg->meb2.exponent); - inp_tgt = tmp_type50_msg->meb2.message; - inp_tgt_len = sizeof(tmp_type50_msg->meb2.message); - } - - mod_tgt += (mod_tgt_len - mod_len); - if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len)) - return SEN_RELEASED; - if (is_empty(mod_tgt, mod_len)) - return SEN_USER_ERROR; - exp_tgt += (exp_tgt_len - mod_len); - if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len)) - return SEN_RELEASED; - if (is_empty(exp_tgt, mod_len)) - return SEN_USER_ERROR; - inp_tgt += (inp_tgt_len - mod_len); - if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len)) - return SEN_RELEASED; - if (is_empty(inp_tgt, mod_len)) - return SEN_USER_ERROR; - - *z90cMsg_l_p = msg_size - CALLER_HEADER; - - return 0; -} - -static int -ICACRT_msg_to_type50CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, - int *z90cMsg_l_p, union type50_msg *z90cMsg_p) -{ - int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len, - dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len, long_offset; - unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt, - temp[8]; - union type50_msg *tmp_type50_msg; - - mod_len = icaMsg_p->inputdatalength; - short_len = mod_len / 2; - long_len = mod_len / 2 + 8; - long_offset = 0; - - if (long_len > 128) { - memset(temp, 0x00, sizeof(temp)); - if (copy_from_user(temp, icaMsg_p->np_prime, long_len-128)) - return SEN_RELEASED; - if (!is_empty(temp, 8)) - return SEN_NOT_AVAIL; - if (copy_from_user(temp, icaMsg_p->bp_key, long_len-128)) - return SEN_RELEASED; - if (!is_empty(temp, 8)) - return SEN_NOT_AVAIL; - if (copy_from_user(temp, icaMsg_p->u_mult_inv, long_len-128)) - return SEN_RELEASED; - if (!is_empty(temp, 8)) - return SEN_NOT_AVAIL; - long_offset = long_len - 128; - long_len = 128; - } - - tmp_size = ((mod_len <= 128) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) + - CALLER_HEADER; - - memset(z90cMsg_p, 0, tmp_size); - - tmp_type50_msg = (union type50_msg *) - ((unsigned char *) z90cMsg_p + CALLER_HEADER); - - tmp_type50_msg->crb1.header.msg_type_code = TYPE50_TYPE_CODE; - if (long_len <= 64) { - tmp_type50_msg->crb1.header.msg_len = TYPE50_CRB1_LEN; - tmp_type50_msg->crb1.keyblock_type = TYPE50_CRB1_FMT; - p_tgt = tmp_type50_msg->crb1.p; - p_tgt_len = sizeof(tmp_type50_msg->crb1.p); - q_tgt = tmp_type50_msg->crb1.q; - q_tgt_len = sizeof(tmp_type50_msg->crb1.q); - dp_tgt = tmp_type50_msg->crb1.dp; - dp_tgt_len = sizeof(tmp_type50_msg->crb1.dp); - dq_tgt = tmp_type50_msg->crb1.dq; - dq_tgt_len = sizeof(tmp_type50_msg->crb1.dq); - u_tgt = tmp_type50_msg->crb1.u; - u_tgt_len = sizeof(tmp_type50_msg->crb1.u); - inp_tgt = tmp_type50_msg->crb1.message; - inp_tgt_len = sizeof(tmp_type50_msg->crb1.message); - } else { - tmp_type50_msg->crb2.header.msg_len = TYPE50_CRB2_LEN; - tmp_type50_msg->crb2.keyblock_type = TYPE50_CRB2_FMT; - p_tgt = tmp_type50_msg->crb2.p; - p_tgt_len = sizeof(tmp_type50_msg->crb2.p); - q_tgt = tmp_type50_msg->crb2.q; - q_tgt_len = sizeof(tmp_type50_msg->crb2.q); - dp_tgt = tmp_type50_msg->crb2.dp; - dp_tgt_len = sizeof(tmp_type50_msg->crb2.dp); - dq_tgt = tmp_type50_msg->crb2.dq; - dq_tgt_len = sizeof(tmp_type50_msg->crb2.dq); - u_tgt = tmp_type50_msg->crb2.u; - u_tgt_len = sizeof(tmp_type50_msg->crb2.u); - inp_tgt = tmp_type50_msg->crb2.message; - inp_tgt_len = sizeof(tmp_type50_msg->crb2.message); - } - - p_tgt += (p_tgt_len - long_len); - if (copy_from_user(p_tgt, icaMsg_p->np_prime + long_offset, long_len)) - return SEN_RELEASED; - if (is_empty(p_tgt, long_len)) - return SEN_USER_ERROR; - q_tgt += (q_tgt_len - short_len); - if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len)) - return SEN_RELEASED; - if (is_empty(q_tgt, short_len)) - return SEN_USER_ERROR; - dp_tgt += (dp_tgt_len - long_len); - if (copy_from_user(dp_tgt, icaMsg_p->bp_key + long_offset, long_len)) - return SEN_RELEASED; - if (is_empty(dp_tgt, long_len)) - return SEN_USER_ERROR; - dq_tgt += (dq_tgt_len - short_len); - if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len)) - return SEN_RELEASED; - if (is_empty(dq_tgt, short_len)) - return SEN_USER_ERROR; - u_tgt += (u_tgt_len - long_len); - if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv + long_offset, long_len)) - return SEN_RELEASED; - if (is_empty(u_tgt, long_len)) - return SEN_USER_ERROR; - inp_tgt += (inp_tgt_len - mod_len); - if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len)) - return SEN_RELEASED; - if (is_empty(inp_tgt, mod_len)) - return SEN_USER_ERROR; - - *z90cMsg_l_p = tmp_size - CALLER_HEADER; - - return 0; -} - int convert_request(unsigned char *buffer, int func, unsigned short function, int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p) @@ -2339,16 +2071,6 @@ convert_request(unsigned char *buffer, int func, unsigned short function, cdx, msg_l_p, (struct type6_msg *) msg_p, dev_type); } - if (dev_type == CEX2A) { - if (func == ICARSACRT) - return ICACRT_msg_to_type50CRT_msg( - (struct ica_rsa_modexpo_crt *) buffer, - msg_l_p, (union type50_msg *) msg_p); - else - return ICAMEX_msg_to_type50MEX_msg( - (struct ica_rsa_modexpo *) buffer, - msg_l_p, (union type50_msg *) msg_p); - } return 0; } @@ -2359,8 +2081,8 @@ unset_ext_bitlens(void) { if (!ext_bitlens_msg_count) { PRINTK("Unable to use coprocessors for extended bitlengths. " - "Using PCICAs/CEX2As (if present) for extended " - "bitlengths. This is not an error.\n"); + "Using PCICAs (if present) for extended bitlengths. " + "This is not an error.\n"); ext_bitlens_msg_count++; } ext_bitlens = 0; @@ -2372,7 +2094,6 @@ convert_response(unsigned char *response, unsigned char *buffer, { struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer; struct error_hdr *errh_p = (struct error_hdr *) response; - struct type80_hdr *t80h_p = (struct type80_hdr *) response; struct type84_hdr *t84h_p = (struct type84_hdr *) response; struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response; int reply_code, service_rc, service_rs, src_l; @@ -2387,7 +2108,6 @@ convert_response(unsigned char *response, unsigned char *buffer, src_l = 0; switch (errh_p->type) { case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: reply_code = errh_p->reply_code; src_p = (unsigned char *)errh_p; PRINTK("Hardware error: Type %02X Message Header: " @@ -2396,10 +2116,6 @@ convert_response(unsigned char *response, unsigned char *buffer, src_p[0], src_p[1], src_p[2], src_p[3], src_p[4], src_p[5], src_p[6], src_p[7]); break; - case TYPE80_RSP_CODE: - src_l = icaMsg_p->outputdatalength; - src_p = response + (int)t80h_p->len - src_l; - break; case TYPE84_RSP_CODE: src_l = icaMsg_p->outputdatalength; src_p = response + (int)t84h_p->len - src_l; @@ -2486,7 +2202,6 @@ convert_response(unsigned char *response, unsigned char *buffer, if (reply_code) switch (reply_code) { case REP82_ERROR_OPERAND_INVALID: - case REP88_ERROR_MESSAGE_MALFORMD: return REC_OPERAND_INV; case REP82_ERROR_OPERAND_SIZE: return REC_OPERAND_SIZE; diff --git a/trunk/drivers/s390/crypto/z90main.c b/trunk/drivers/s390/crypto/z90main.c index 135ae04e6e75..790fcbb74b43 100644 --- a/trunk/drivers/s390/crypto/z90main.c +++ b/trunk/drivers/s390/crypto/z90main.c @@ -228,7 +228,7 @@ struct device_x { */ struct device { int dev_type; // PCICA, PCICC, PCIXCC_MCL2, - // PCIXCC_MCL3, CEX2C, CEX2A + // PCIXCC_MCL3, CEX2C enum devstat dev_stat; // current device status int dev_self_x; // Index in array int disabled; // Set when device is in error @@ -295,30 +295,26 @@ struct caller { /** * Function prototypes from z90hardware.c */ -enum hdstat query_online(int deviceNr, int cdx, int resetNr, int *q_depth, - int *dev_type); -enum devstat reset_device(int deviceNr, int cdx, int resetNr); -enum devstat send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext); -enum devstat receive_from_AP(int dev_nr, int cdx, int resplen, - unsigned char *resp, unsigned char *psmid); -int convert_request(unsigned char *buffer, int func, unsigned short function, - int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p); -int convert_response(unsigned char *response, unsigned char *buffer, - int *respbufflen_p, unsigned char *resp_buff); +enum hdstat query_online(int, int, int, int *, int *); +enum devstat reset_device(int, int, int); +enum devstat send_to_AP(int, int, int, unsigned char *); +enum devstat receive_from_AP(int, int, int, unsigned char *, unsigned char *); +int convert_request(unsigned char *, int, short, int, int, int *, + unsigned char *); +int convert_response(unsigned char *, unsigned char *, int *, unsigned char *); /** * Low level function prototypes */ -static int create_z90crypt(int *cdx_p); -static int refresh_z90crypt(int *cdx_p); -static int find_crypto_devices(struct status *deviceMask); -static int create_crypto_device(int index); -static int destroy_crypto_device(int index); +static int create_z90crypt(int *); +static int refresh_z90crypt(int *); +static int find_crypto_devices(struct status *); +static int create_crypto_device(int); +static int destroy_crypto_device(int); static void destroy_z90crypt(void); -static int refresh_index_array(struct status *status_str, - struct device_x *index_array); -static int probe_device_type(struct device *devPtr); -static int probe_PCIXCC_type(struct device *devPtr); +static int refresh_index_array(struct status *, struct device_x *); +static int probe_device_type(struct device *); +static int probe_PCIXCC_type(struct device *); /** * proc fs definitions @@ -429,7 +425,7 @@ static struct miscdevice z90crypt_misc_device = { MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman" "and Jochen Roehrig"); MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, " - "Copyright 2001, 2005 IBM Corporation"); + "Copyright 2001, 2004 IBM Corporation"); MODULE_LICENSE("GPL"); module_param(domain, int, 0); MODULE_PARM_DESC(domain, "domain index for device"); @@ -863,12 +859,6 @@ get_status_CEX2Ccount(void) return z90crypt.hdware_info->type_mask[CEX2C].st_count; } -static inline int -get_status_CEX2Acount(void) -{ - return z90crypt.hdware_info->type_mask[CEX2A].st_count; -} - static inline int get_status_requestq_count(void) { @@ -1018,13 +1008,11 @@ static inline int select_device_type(int *dev_type_p, int bytelength) { static int count = 0; - int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, CEX2A_avail, - index_to_use; + int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use; struct status *stat; if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) && (*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) && - (*dev_type_p != CEX2C) && (*dev_type_p != CEX2A) && - (*dev_type_p != ANYDEV)) + (*dev_type_p != CEX2C) && (*dev_type_p != ANYDEV)) return -1; if (*dev_type_p != ANYDEV) { stat = &z90crypt.hdware_info->type_mask[*dev_type_p]; @@ -1034,13 +1022,7 @@ select_device_type(int *dev_type_p, int bytelength) return -1; } - /** - * Assumption: PCICA, PCIXCC_MCL3, CEX2C, and CEX2A are all similar in - * speed. - * - * PCICA and CEX2A do NOT co-exist, so it would be either one or the - * other present. - */ + /* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */ stat = &z90crypt.hdware_info->type_mask[PCICA]; PCICA_avail = stat->st_count - (stat->disabled_count + stat->user_disabled_count); @@ -1050,38 +1032,29 @@ select_device_type(int *dev_type_p, int bytelength) stat = &z90crypt.hdware_info->type_mask[CEX2C]; CEX2C_avail = stat->st_count - (stat->disabled_count + stat->user_disabled_count); - stat = &z90crypt.hdware_info->type_mask[CEX2A]; - CEX2A_avail = stat->st_count - - (stat->disabled_count + stat->user_disabled_count); - if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail || CEX2A_avail) { + if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) { /** - * bitlength is a factor, PCICA or CEX2A are the most capable, - * even with the new MCL for PCIXCC. + * bitlength is a factor, PCICA is the most capable, even with + * the new MCL for PCIXCC. */ if ((bytelength < PCIXCC_MIN_MOD_SIZE) || (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) { - if (PCICA_avail) { + if (!PCICA_avail) + return -1; + else { *dev_type_p = PCICA; return 0; } - if (CEX2A_avail) { - *dev_type_p = CEX2A; - return 0; - } - return -1; } index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail + - CEX2C_avail + CEX2A_avail); + CEX2C_avail); if (index_to_use < PCICA_avail) *dev_type_p = PCICA; else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail)) *dev_type_p = PCIXCC_MCL3; - else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail + - CEX2C_avail)) - *dev_type_p = CEX2C; else - *dev_type_p = CEX2A; + *dev_type_p = CEX2C; count++; return 0; } @@ -1386,7 +1359,7 @@ build_caller(struct work_element *we_p, short function) if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) && (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) && - (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A)) + (we_p->devtype != CEX2C)) return SEN_NOT_AVAIL; memcpy(caller_p->caller_id, we_p->caller_id, @@ -1455,8 +1428,7 @@ get_crypto_request_buffer(struct work_element *we_p) if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) && (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) && - (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A) && - (we_p->devtype != ANYDEV)) { + (we_p->devtype != CEX2C) && (we_p->devtype != ANYDEV)) { PRINTK("invalid device type\n"); return SEN_USER_ERROR; } @@ -1531,9 +1503,8 @@ get_crypto_request_buffer(struct work_element *we_p) function = PCI_FUNC_KEY_ENCRYPT; switch (we_p->devtype) { - /* PCICA and CEX2A do everything with a simple RSA mod-expo operation */ + /* PCICA does everything with a simple RSA mod-expo operation */ case PCICA: - case CEX2A: function = PCI_FUNC_KEY_ENCRYPT; break; /** @@ -1691,8 +1662,7 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid, * trigger a fallback to software. */ case -EINVAL: - if ((we_p->devtype != PCICA) && - (we_p->devtype != CEX2A)) + if (we_p->devtype != PCICA) rv = -EGETBUFF; break; case -ETIMEOUT: @@ -1809,12 +1779,6 @@ z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ret = -EFAULT; break; - case Z90STAT_CEX2ACOUNT: - tempstat = get_status_CEX2Acount(); - if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) - ret = -EFAULT; - break; - case Z90STAT_REQUESTQ_COUNT: tempstat = get_status_requestq_count(); if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) @@ -2055,8 +2019,6 @@ z90crypt_status(char *resp_buff, char **start, off_t offset, get_status_PCIXCCMCL3count()); len += sprintf(resp_buff+len, "CEX2C count: %d\n", get_status_CEX2Ccount()); - len += sprintf(resp_buff+len, "CEX2A count: %d\n", - get_status_CEX2Acount()); len += sprintf(resp_buff+len, "requestq count: %d\n", get_status_requestq_count()); len += sprintf(resp_buff+len, "pendingq count: %d\n", @@ -2064,8 +2026,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset, len += sprintf(resp_buff+len, "Total open handles: %d\n\n", get_status_totalopen_count()); len += sprinthx( - "Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) " - "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A", + "Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), " + "4: PCIXCC (MCL3), 5: CEX2C", resp_buff+len, get_status_status_mask(workarea), Z90CRYPT_NUM_APS); @@ -2178,7 +2140,6 @@ z90crypt_status_write(struct file *file, const char __user *buffer, case '3': // PCIXCC_MCL2 case '4': // PCIXCC_MCL3 case '5': // CEX2C - case '6': // CEX2A j++; break; case 'd': @@ -3046,9 +3007,7 @@ create_crypto_device(int index) z90crypt.hdware_info->device_type_array[index] = 4; else if (deviceType == CEX2C) z90crypt.hdware_info->device_type_array[index] = 5; - else if (deviceType == CEX2A) - z90crypt.hdware_info->device_type_array[index] = 6; - else // No idea how this would happen. + else z90crypt.hdware_info->device_type_array[index] = -1; } diff --git a/trunk/drivers/s390/net/Kconfig b/trunk/drivers/s390/net/Kconfig index 548854754921..a7efc394515e 100644 --- a/trunk/drivers/s390/net/Kconfig +++ b/trunk/drivers/s390/net/Kconfig @@ -1,5 +1,5 @@ menu "S/390 network device drivers" - depends on NETDEVICES && S390 + depends on NETDEVICES && ARCH_S390 config LCS tristate "Lan Channel Station Interface" diff --git a/trunk/drivers/s390/net/claw.c b/trunk/drivers/s390/net/claw.c index e70af7f39946..6b63d21612ec 100644 --- a/trunk/drivers/s390/net/claw.c +++ b/trunk/drivers/s390/net/claw.c @@ -1603,7 +1603,7 @@ dumpit(char* buf, int len) __u32 ct, sw, rm, dup; char *ptr, *rptr; char tbuf[82], tdup[82]; -#if (CONFIG_64BIT) +#if (CONFIG_ARCH_S390X) char addr[22]; #else char addr[12]; @@ -1619,7 +1619,7 @@ dumpit(char* buf, int len) dup = 0; for ( ct=0; ct < len; ct++, ptr++, rptr++ ) { if (sw == 0) { -#if (CONFIG_64BIT) +#if (CONFIG_ARCH_S390X) sprintf(addr, "%16.16lX",(unsigned long)rptr); #else sprintf(addr, "%8.8X",(__u32)rptr); @@ -1634,7 +1634,7 @@ dumpit(char* buf, int len) if (sw == 8) { strcat(bhex, " "); } -#if (CONFIG_64BIT) +#if (CONFIG_ARCH_S390X) sprintf(tbuf,"%2.2lX", (unsigned long)*ptr); #else sprintf(tbuf,"%2.2X", (__u32)*ptr); diff --git a/trunk/drivers/s390/net/cu3088.c b/trunk/drivers/s390/net/cu3088.c index 77dacb465732..0075894c71db 100644 --- a/trunk/drivers/s390/net/cu3088.c +++ b/trunk/drivers/s390/net/cu3088.c @@ -1,5 +1,5 @@ /* - * $Id: cu3088.c,v 1.36 2005/10/25 14:37:17 cohuck Exp $ + * $Id: cu3088.c,v 1.35 2005/03/30 19:28:52 richtera Exp $ * * CTC / LCS ccw_device driver * @@ -27,7 +27,6 @@ #include #include -#include #include #include diff --git a/trunk/drivers/s390/net/iucv.c b/trunk/drivers/s390/net/iucv.c index ea8177392564..df7647c3c100 100644 --- a/trunk/drivers/s390/net/iucv.c +++ b/trunk/drivers/s390/net/iucv.c @@ -1,5 +1,5 @@ /* - * $Id: iucv.c,v 1.47 2005/11/21 11:35:22 mschwide Exp $ + * $Id: iucv.c,v 1.45 2005/04/26 22:59:06 braunu Exp $ * * IUCV network driver * @@ -29,7 +29,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.47 $ + * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.45 $ * */ @@ -54,7 +54,7 @@ #include #include #include -#include +#include //for root device stuff /* FLAGS: * All flags are defined in the field IPFLAGS1 of each function @@ -355,7 +355,7 @@ do { \ static void iucv_banner(void) { - char vbuf[] = "$Revision: 1.47 $"; + char vbuf[] = "$Revision: 1.45 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { @@ -477,7 +477,7 @@ grab_param(void) ptr++; if (ptr >= iucv_param_pool + PARAM_POOL_SIZE) ptr = iucv_param_pool; - } while (atomic_cmpxchg(&ptr->in_use, 0, 1) != 0); + } while (atomic_compare_and_swap(0, 1, &ptr->in_use)); hint = ptr - iucv_param_pool; memset(&ptr->param, 0, sizeof(ptr->param)); diff --git a/trunk/drivers/s390/net/qeth_main.c b/trunk/drivers/s390/net/qeth_main.c index 97f927c01a82..f8f55cc468ba 100644 --- a/trunk/drivers/s390/net/qeth_main.c +++ b/trunk/drivers/s390/net/qeth_main.c @@ -65,7 +65,6 @@ #include #include #include -#include #include "qeth.h" #include "qeth_mpc.h" @@ -1397,7 +1396,7 @@ qeth_idx_activate_get_answer(struct qeth_channel *channel, channel->ccw.cda = (__u32) __pa(iob->data); wait_event(card->wait_q, - atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0); + atomic_compare_and_swap(0,1,&channel->irq_pending) == 0); QETH_DBF_TEXT(setup, 6, "noirqpnd"); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); rc = ccw_device_start(channel->ccwdev, @@ -1464,7 +1463,7 @@ qeth_idx_activate_channel(struct qeth_channel *channel, memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(iob->data), &temp, 2); wait_event(card->wait_q, - atomic_cmpxchg(&channel->irq_pending, 0, 1) == 0); + atomic_compare_and_swap(0,1,&channel->irq_pending) == 0); QETH_DBF_TEXT(setup, 6, "noirqpnd"); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); rc = ccw_device_start(channel->ccwdev, @@ -1617,7 +1616,7 @@ qeth_issue_next_read(struct qeth_card *card) } qeth_setup_ccw(&card->read, iob->data, QETH_BUFSIZE); wait_event(card->wait_q, - atomic_cmpxchg(&card->read.irq_pending, 0, 1) == 0); + atomic_compare_and_swap(0,1,&card->read.irq_pending) == 0); QETH_DBF_TEXT(trace, 6, "noirqpnd"); rc = ccw_device_start(card->read.ccwdev, &card->read.ccw, (addr_t) iob, 0, 0); @@ -1883,7 +1882,7 @@ qeth_send_control_data(struct qeth_card *card, int len, spin_unlock_irqrestore(&card->lock, flags); QETH_DBF_HEX(control, 2, iob->data, QETH_DBF_CONTROL_LEN); wait_event(card->wait_q, - atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0); + atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0); qeth_prepare_control_data(card, len, iob); if (IS_IPA(iob->data)) timer.expires = jiffies + QETH_IPA_TIMEOUT; @@ -1925,7 +1924,7 @@ qeth_osn_send_control_data(struct qeth_card *card, int len, QETH_DBF_TEXT(trace, 5, "osndctrd"); wait_event(card->wait_q, - atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0); + atomic_compare_and_swap(0,1,&card->write.irq_pending) == 0); qeth_prepare_control_data(card, len, iob); QETH_DBF_TEXT(trace, 6, "osnoirqp"); spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags); @@ -4237,8 +4236,9 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, QETH_DBF_TEXT(trace, 6, "dosndpfa"); /* spin until we get the queue ... */ - while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, - QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); + while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED, + QETH_OUT_Q_LOCKED, + &queue->state)); /* ... now we've got the queue */ index = queue->next_buf_to_fill; buffer = &queue->bufs[queue->next_buf_to_fill]; @@ -4292,8 +4292,9 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, QETH_DBF_TEXT(trace, 6, "dosndpkt"); /* spin until we get the queue ... */ - while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, - QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); + while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED, + QETH_OUT_Q_LOCKED, + &queue->state)); start_index = queue->next_buf_to_fill; buffer = &queue->bufs[queue->next_buf_to_fill]; /* diff --git a/trunk/drivers/s390/s390_rdev.c b/trunk/drivers/s390/s390_rdev.c deleted file mode 100644 index 566cc3d185b6..000000000000 --- a/trunk/drivers/s390/s390_rdev.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * drivers/s390/s390_rdev.c - * s390 root device - * $Revision: 1.2 $ - * - * Copyright (C) 2002, 2005 IBM Deutschland Entwicklung GmbH, - * IBM Corporation - * Author(s): Cornelia Huck (cohuck@de.ibm.com) - * Carsten Otte (cotte@de.ibm.com) - */ - -#include -#include -#include -#include - -static void -s390_root_dev_release(struct device *dev) -{ - kfree(dev); -} - -struct device * -s390_root_dev_register(const char *name) -{ - struct device *dev; - int ret; - - if (!strlen(name)) - return ERR_PTR(-EINVAL); - dev = kmalloc(sizeof(struct device), GFP_KERNEL); - if (!dev) - return ERR_PTR(-ENOMEM); - memset(dev, 0, sizeof(struct device)); - strncpy(dev->bus_id, name, min(strlen(name), (size_t)BUS_ID_SIZE)); - dev->release = s390_root_dev_release; - ret = device_register(dev); - if (ret) { - kfree(dev); - return ERR_PTR(ret); - } - return dev; -} - -void -s390_root_dev_unregister(struct device *dev) -{ - if (dev) - device_unregister(dev); -} - -EXPORT_SYMBOL(s390_root_dev_register); -EXPORT_SYMBOL(s390_root_dev_unregister); diff --git a/trunk/drivers/s390/s390mach.c b/trunk/drivers/s390/s390mach.c index 3bf466603512..4191fd9d4d11 100644 --- a/trunk/drivers/s390/s390mach.c +++ b/trunk/drivers/s390/s390mach.c @@ -23,7 +23,7 @@ static struct semaphore m_sem; -extern int css_process_crw(int, int); +extern int css_process_crw(int); extern int chsc_process_crw(void); extern int chp_process_crw(int, int); extern void css_reiterate_subchannels(void); @@ -49,10 +49,9 @@ s390_handle_damage(char *msg) static int s390_collect_crw_info(void *param) { - struct crw crw[2]; + struct crw crw; int ccode, ret, slow; struct semaphore *sem; - unsigned int chain; sem = (struct semaphore *)param; /* Set a nice name. */ @@ -60,50 +59,25 @@ s390_collect_crw_info(void *param) repeat: down_interruptible(sem); slow = 0; - chain = 0; while (1) { - if (unlikely(chain > 1)) { - struct crw tmp_crw; - - printk(KERN_WARNING"%s: Code does not support more " - "than two chained crws; please report to " - "linux390@de.ibm.com!\n", __FUNCTION__); - ccode = stcrw(&tmp_crw); - printk(KERN_WARNING"%s: crw reports slct=%d, oflw=%d, " - "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", - __FUNCTION__, tmp_crw.slct, tmp_crw.oflw, - tmp_crw.chn, tmp_crw.rsc, tmp_crw.anc, - tmp_crw.erc, tmp_crw.rsid); - printk(KERN_WARNING"%s: This was crw number %x in the " - "chain\n", __FUNCTION__, chain); - if (ccode != 0) - break; - chain = tmp_crw.chn ? chain + 1 : 0; - continue; - } - ccode = stcrw(&crw[chain]); + ccode = stcrw(&crw); if (ccode != 0) break; DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", - crw[chain].slct, crw[chain].oflw, crw[chain].chn, - crw[chain].rsc, crw[chain].anc, crw[chain].erc, - crw[chain].rsid); + crw.slct, crw.oflw, crw.chn, crw.rsc, crw.anc, + crw.erc, crw.rsid); /* Check for overflows. */ - if (crw[chain].oflw) { + if (crw.oflw) { pr_debug("%s: crw overflow detected!\n", __FUNCTION__); css_reiterate_subchannels(); - chain = 0; slow = 1; continue; } - switch (crw[chain].rsc) { + switch (crw.rsc) { case CRW_RSC_SCH: - if (crw[0].chn && !chain) - break; - pr_debug("source is subchannel %04X\n", crw[0].rsid); - ret = css_process_crw (crw[0].rsid, - chain ? crw[1].rsid : 0); + pr_debug("source is subchannel %04X\n", crw.rsid); + ret = css_process_crw (crw.rsid); if (ret == -EAGAIN) slow = 1; break; @@ -111,18 +85,18 @@ s390_collect_crw_info(void *param) pr_debug("source is monitoring facility\n"); break; case CRW_RSC_CPATH: - pr_debug("source is channel path %02X\n", crw[0].rsid); - switch (crw[0].erc) { + pr_debug("source is channel path %02X\n", crw.rsid); + switch (crw.erc) { case CRW_ERC_IPARM: /* Path has come. */ - ret = chp_process_crw(crw[0].rsid, 1); + ret = chp_process_crw(crw.rsid, 1); break; case CRW_ERC_PERRI: /* Path has gone. */ case CRW_ERC_PERRN: - ret = chp_process_crw(crw[0].rsid, 0); + ret = chp_process_crw(crw.rsid, 0); break; default: pr_debug("Don't know how to handle erc=%x\n", - crw[0].erc); + crw.erc); ret = 0; } if (ret == -EAGAIN) @@ -141,8 +115,6 @@ s390_collect_crw_info(void *param) pr_debug("unknown source\n"); break; } - /* chain is always 0 or 1 here. */ - chain = crw[chain].chn ? chain + 1 : 0; } if (slow) queue_work(slow_path_wq, &slow_path_work); @@ -246,7 +218,7 @@ s390_revalidate_registers(struct mci *mci) */ kill_task = 1; -#ifndef CONFIG_64BIT +#ifndef __s390x__ asm volatile("ld 0,0(%0)\n" "ld 2,8(%0)\n" "ld 4,16(%0)\n" @@ -255,7 +227,7 @@ s390_revalidate_registers(struct mci *mci) #endif if (MACHINE_HAS_IEEE) { -#ifdef CONFIG_64BIT +#ifdef __s390x__ fpt_save_area = &S390_lowcore.floating_pt_save_area; fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area; #else @@ -314,7 +286,7 @@ s390_revalidate_registers(struct mci *mci) */ s390_handle_damage("invalid control registers."); else -#ifdef CONFIG_64BIT +#ifdef __s390x__ asm volatile("lctlg 0,15,0(%0)" : : "a" (&S390_lowcore.cregs_save_area)); #else @@ -327,7 +299,7 @@ s390_revalidate_registers(struct mci *mci) * can't write something sensible into that register. */ -#ifdef CONFIG_64BIT +#ifdef __s390x__ /* * See if we can revalidate the TOD programmable register with its * old contents (should be zero) otherwise set it to zero. @@ -384,7 +356,7 @@ s390_do_machine_check(struct pt_regs *regs) if (mci->b) { /* Processing backup -> verify if we can survive this */ u64 z_mcic, o_mcic, t_mcic; -#ifdef CONFIG_64BIT +#ifdef __s390x__ z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29); o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 | 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 | diff --git a/trunk/drivers/s390/sysinfo.c b/trunk/drivers/s390/sysinfo.c index 66da840c9316..87c2db1bd4f5 100644 --- a/trunk/drivers/s390/sysinfo.c +++ b/trunk/drivers/s390/sysinfo.c @@ -106,7 +106,7 @@ static inline int stsi (void *sysinfo, { int cc, retv; -#ifndef CONFIG_64BIT +#ifndef CONFIG_ARCH_S390X __asm__ __volatile__ ( "lr\t0,%2\n" "\tlr\t1,%3\n" "\tstsi\t0(%4)\n" diff --git a/trunk/drivers/scsi/Kconfig b/trunk/drivers/scsi/Kconfig index 3c606cf8c8ca..4c42065dea88 100644 --- a/trunk/drivers/scsi/Kconfig +++ b/trunk/drivers/scsi/Kconfig @@ -914,7 +914,7 @@ config SCSI_INIA100 config SCSI_PPA tristate "IOMEGA parallel port (ppa - older drives)" - depends on SCSI && PARPORT_PC + depends on SCSI && PARPORT ---help--- This driver supports older versions of IOMEGA's parallel port ZIP drive (a 100 MB removable media device). @@ -941,7 +941,7 @@ config SCSI_PPA config SCSI_IMM tristate "IOMEGA parallel port (imm - newer drives)" - depends on SCSI && PARPORT_PC + depends on SCSI && PARPORT ---help--- This driver supports newer versions of IOMEGA's parallel port ZIP drive (a 100 MB removable media device). @@ -968,7 +968,7 @@ config SCSI_IMM config SCSI_IZIP_EPP16 bool "ppa/imm option - Use slow (but safe) EPP-16" - depends on SCSI_PPA || SCSI_IMM + depends on PARPORT && (SCSI_PPA || SCSI_IMM) ---help--- EPP (Enhanced Parallel Port) is a standard for parallel ports which allows them to act as expansion buses that can handle up to 64 @@ -983,7 +983,7 @@ config SCSI_IZIP_EPP16 config SCSI_IZIP_SLOW_CTR bool "ppa/imm option - Assume slow parport control register" - depends on SCSI_PPA || SCSI_IMM + depends on PARPORT && (SCSI_PPA || SCSI_IMM) help Some parallel ports are known to have excessive delays between changing the parallel port control register and good data being @@ -1815,7 +1815,7 @@ config SCSI_SUNESP config ZFCP tristate "FCP host bus adapter driver for IBM eServer zSeries" - depends on S390 && QDIO && SCSI + depends on ARCH_S390 && QDIO && SCSI select SCSI_FC_ATTRS help If you want to access SCSI devices attached to your IBM eServer diff --git a/trunk/drivers/scsi/ahci.c b/trunk/drivers/scsi/ahci.c index d113290b5fc0..887eaa2a3ebf 100644 --- a/trunk/drivers/scsi/ahci.c +++ b/trunk/drivers/scsi/ahci.c @@ -214,6 +214,7 @@ static struct scsi_host_template ahci_sht = { .dma_boundary = AHCI_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; static const struct ata_port_operations ahci_ops = { diff --git a/trunk/drivers/scsi/ata_piix.c b/trunk/drivers/scsi/ata_piix.c index 557788ec4eec..0ea27873b9ff 100644 --- a/trunk/drivers/scsi/ata_piix.c +++ b/trunk/drivers/scsi/ata_piix.c @@ -166,8 +166,6 @@ static struct pci_driver piix_pci_driver = { .id_table = piix_pci_tbl, .probe = piix_init_one, .remove = ata_pci_remove_one, - .suspend = ata_pci_device_suspend, - .resume = ata_pci_device_resume, }; static struct scsi_host_template piix_sht = { @@ -187,8 +185,7 @@ static struct scsi_host_template piix_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, - .resume = ata_scsi_device_resume, - .suspend = ata_scsi_device_suspend, + .ordered_flush = 1, }; static const struct ata_port_operations piix_pata_ops = { diff --git a/trunk/drivers/scsi/hosts.c b/trunk/drivers/scsi/hosts.c index 66783c860a19..5b9c2c5a7f0e 100644 --- a/trunk/drivers/scsi/hosts.c +++ b/trunk/drivers/scsi/hosts.c @@ -347,8 +347,17 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->cmd_per_lun = sht->cmd_per_lun; shost->unchecked_isa_dma = sht->unchecked_isa_dma; shost->use_clustering = sht->use_clustering; + shost->ordered_flush = sht->ordered_flush; shost->ordered_tag = sht->ordered_tag; + /* + * hosts/devices that do queueing must support ordered tags + */ + if (shost->can_queue > 1 && shost->ordered_flush) { + printk(KERN_ERR "scsi: ordered flushes don't support queueing\n"); + shost->ordered_flush = 0; + } + if (sht->max_host_blocked) shost->max_host_blocked = sht->max_host_blocked; else diff --git a/trunk/drivers/scsi/ide-scsi.c b/trunk/drivers/scsi/ide-scsi.c index 3c688ef54660..4cb1f3ed9100 100644 --- a/trunk/drivers/scsi/ide-scsi.c +++ b/trunk/drivers/scsi/ide-scsi.c @@ -1046,7 +1046,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) /* kill current request */ blkdev_dequeue_request(req); - end_that_request_last(req, 0); + end_that_request_last(req); if (req->flags & REQ_SENSE) kfree(scsi->pc->buffer); kfree(scsi->pc); @@ -1056,7 +1056,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) /* now nuke the drive queue */ while ((req = elv_next_request(drive->queue))) { blkdev_dequeue_request(req); - end_that_request_last(req, 0); + end_that_request_last(req); } HWGROUP(drive)->rq = NULL; diff --git a/trunk/drivers/scsi/libata-core.c b/trunk/drivers/scsi/libata-core.c index f55b9b3f7b37..9ea102587914 100644 --- a/trunk/drivers/scsi/libata-core.c +++ b/trunk/drivers/scsi/libata-core.c @@ -562,28 +562,16 @@ static const u8 ata_rw_cmds[] = { ATA_CMD_WRITE_MULTI, ATA_CMD_READ_MULTI_EXT, ATA_CMD_WRITE_MULTI_EXT, - 0, - 0, - 0, - ATA_CMD_WRITE_MULTI_FUA_EXT, /* pio */ ATA_CMD_PIO_READ, ATA_CMD_PIO_WRITE, ATA_CMD_PIO_READ_EXT, ATA_CMD_PIO_WRITE_EXT, - 0, - 0, - 0, - 0, /* dma */ ATA_CMD_READ, ATA_CMD_WRITE, ATA_CMD_READ_EXT, - ATA_CMD_WRITE_EXT, - 0, - 0, - 0, - ATA_CMD_WRITE_FUA_EXT + ATA_CMD_WRITE_EXT }; /** @@ -596,32 +584,25 @@ static const u8 ata_rw_cmds[] = { * LOCKING: * caller. */ -int ata_rwcmd_protocol(struct ata_queued_cmd *qc) +void ata_rwcmd_protocol(struct ata_queued_cmd *qc) { struct ata_taskfile *tf = &qc->tf; struct ata_device *dev = qc->dev; - u8 cmd; - int index, fua, lba48, write; + int index, lba48, write; - fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0; lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0; write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0; if (dev->flags & ATA_DFLAG_PIO) { tf->protocol = ATA_PROT_PIO; - index = dev->multi_count ? 0 : 8; + index = dev->multi_count ? 0 : 4; } else { tf->protocol = ATA_PROT_DMA; - index = 16; + index = 8; } - cmd = ata_rw_cmds[index + fua + lba48 + write]; - if (cmd) { - tf->command = cmd; - return 0; - } - return -1; + tf->command = ata_rw_cmds[index + lba48 + write]; } static const char * const xfer_mode_str[] = { @@ -4173,96 +4154,6 @@ static void atapi_packet_task(void *_data) * Inherited from caller. */ -/* - * Execute a 'simple' command, that only consists of the opcode 'cmd' itself, - * without filling any other registers - */ -static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev, - u8 cmd) -{ - struct ata_taskfile tf; - int err; - - ata_tf_init(ap, &tf, dev->devno); - - tf.command = cmd; - tf.flags |= ATA_TFLAG_DEVICE; - tf.protocol = ATA_PROT_NODATA; - - err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); - if (err) - printk(KERN_ERR "%s: ata command failed: %d\n", - __FUNCTION__, err); - - return err; -} - -static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev) -{ - u8 cmd; - - if (!ata_try_flush_cache(dev)) - return 0; - - if (ata_id_has_flush_ext(dev->id)) - cmd = ATA_CMD_FLUSH_EXT; - else - cmd = ATA_CMD_FLUSH; - - return ata_do_simple_cmd(ap, dev, cmd); -} - -static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev) -{ - return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1); -} - -static int ata_start_drive(struct ata_port *ap, struct ata_device *dev) -{ - return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE); -} - -/** - * ata_device_resume - wakeup a previously suspended devices - * - * Kick the drive back into action, by sending it an idle immediate - * command and making sure its transfer mode matches between drive - * and host. - * - */ -int ata_device_resume(struct ata_port *ap, struct ata_device *dev) -{ - if (ap->flags & ATA_FLAG_SUSPENDED) { - ap->flags &= ~ATA_FLAG_SUSPENDED; - ata_set_mode(ap); - } - if (!ata_dev_present(dev)) - return 0; - if (dev->class == ATA_DEV_ATA) - ata_start_drive(ap, dev); - - return 0; -} - -/** - * ata_device_suspend - prepare a device for suspend - * - * Flush the cache on the drive, if appropriate, then issue a - * standbynow command. - * - */ -int ata_device_suspend(struct ata_port *ap, struct ata_device *dev) -{ - if (!ata_dev_present(dev)) - return 0; - if (dev->class == ATA_DEV_ATA) - ata_flush_cache(ap, dev); - - ata_standby_drive(ap, dev); - ap->flags |= ATA_FLAG_SUSPENDED; - return 0; -} - int ata_port_start (struct ata_port *ap) { struct device *dev = ap->host_set->dev; @@ -5011,23 +4902,6 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits) return (tmp == bits->val) ? 1 : 0; } - -int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state) -{ - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - return 0; -} - -int ata_pci_device_resume(struct pci_dev *pdev) -{ - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_device(pdev); - pci_set_master(pdev); - return 0; -} #endif /* CONFIG_PCI */ @@ -5131,11 +5005,4 @@ EXPORT_SYMBOL_GPL(ata_pci_host_stop); EXPORT_SYMBOL_GPL(ata_pci_init_native_mode); EXPORT_SYMBOL_GPL(ata_pci_init_one); EXPORT_SYMBOL_GPL(ata_pci_remove_one); -EXPORT_SYMBOL_GPL(ata_pci_device_suspend); -EXPORT_SYMBOL_GPL(ata_pci_device_resume); #endif /* CONFIG_PCI */ - -EXPORT_SYMBOL_GPL(ata_device_suspend); -EXPORT_SYMBOL_GPL(ata_device_resume); -EXPORT_SYMBOL_GPL(ata_scsi_device_suspend); -EXPORT_SYMBOL_GPL(ata_scsi_device_resume); diff --git a/trunk/drivers/scsi/libata-scsi.c b/trunk/drivers/scsi/libata-scsi.c index cfbceb504718..e0439be4b573 100644 --- a/trunk/drivers/scsi/libata-scsi.c +++ b/trunk/drivers/scsi/libata-scsi.c @@ -396,22 +396,6 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf) } } -int ata_scsi_device_resume(struct scsi_device *sdev) -{ - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; - struct ata_device *dev = &ap->device[sdev->id]; - - return ata_device_resume(ap, dev); -} - -int ata_scsi_device_suspend(struct scsi_device *sdev) -{ - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; - struct ata_device *dev = &ap->device[sdev->id]; - - return ata_device_suspend(ap, dev); -} - /** * ata_to_sense_error - convert ATA error to SCSI error * @id: ATA device number @@ -1096,13 +1080,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm scsicmd[0] == WRITE_16) tf->flags |= ATA_TFLAG_WRITE; - /* Calculate the SCSI LBA, transfer length and FUA. */ + /* Calculate the SCSI LBA and transfer length. */ switch (scsicmd[0]) { case READ_10: case WRITE_10: scsi_10_lba_len(scsicmd, &block, &n_block); - if (unlikely(scsicmd[1] & (1 << 3))) - tf->flags |= ATA_TFLAG_FUA; break; case READ_6: case WRITE_6: @@ -1117,8 +1099,6 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm case READ_16: case WRITE_16: scsi_16_lba_len(scsicmd, &block, &n_block); - if (unlikely(scsicmd[1] & (1 << 3))) - tf->flags |= ATA_TFLAG_FUA; break; default: DPRINTK("no-byte command\n"); @@ -1162,8 +1142,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm tf->device |= (block >> 24) & 0xf; } - if (unlikely(ata_rwcmd_protocol(qc) < 0)) - goto invalid_fld; + ata_rwcmd_protocol(qc); qc->nsect = n_block; tf->nsect = n_block & 0xff; @@ -1181,8 +1160,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm if ((block >> 28) || (n_block > 256)) goto out_of_range; - if (unlikely(ata_rwcmd_protocol(qc) < 0)) - goto invalid_fld; + ata_rwcmd_protocol(qc); /* Convert LBA to CHS */ track = (u32)block / dev->sectors; @@ -1717,7 +1695,6 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { - struct ata_device *dev = args->dev; u8 *scsicmd = args->cmd->cmnd, *p, *last; const u8 sat_blk_desc[] = { 0, 0, 0, 0, /* number of blocks: sat unspecified */ @@ -1726,7 +1703,6 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, }; u8 pg, spg; unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen; - u8 dpofua; VPRINTK("ENTER\n"); @@ -1795,17 +1771,9 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, if (minlen < 1) return 0; - - dpofua = 0; - if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && - (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) - dpofua = 1 << 4; - if (six_byte) { output_len--; rbuf[0] = output_len; - if (minlen > 2) - rbuf[2] |= dpofua; if (ebd) { if (minlen > 3) rbuf[3] = sizeof(sat_blk_desc); @@ -1818,8 +1786,6 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, rbuf[0] = output_len >> 8; if (minlen > 1) rbuf[1] = output_len; - if (minlen > 3) - rbuf[3] |= dpofua; if (ebd) { if (minlen > 7) rbuf[7] = sizeof(sat_blk_desc); @@ -2480,7 +2446,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) if (xlat_func) ata_scsi_translate(ap, dev, cmd, done, xlat_func); else - ata_scsi_simulate(ap, dev, cmd, done); + ata_scsi_simulate(dev->id, cmd, done); } else ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); @@ -2503,16 +2469,14 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) * spin_lock_irqsave(host_set lock) */ -void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, +void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ata_scsi_args args; const u8 *scsicmd = cmd->cmnd; - args.ap = ap; - args.dev = dev; - args.id = dev->id; + args.id = id; args.cmd = cmd; args.done = done; diff --git a/trunk/drivers/scsi/libata.h b/trunk/drivers/scsi/libata.h index e03ce48b7b4b..251e53bdc6e0 100644 --- a/trunk/drivers/scsi/libata.h +++ b/trunk/drivers/scsi/libata.h @@ -32,8 +32,6 @@ #define DRV_VERSION "1.20" /* must be exactly four chars */ struct ata_scsi_args { - struct ata_port *ap; - struct ata_device *dev; u16 *id; struct scsi_cmnd *cmd; void (*done)(struct scsi_cmnd *); @@ -43,7 +41,7 @@ struct ata_scsi_args { extern int atapi_enabled; extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, struct ata_device *dev); -extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); +extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); extern int ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); diff --git a/trunk/drivers/scsi/sata_mv.c b/trunk/drivers/scsi/sata_mv.c index cd54244058b5..b2bf16a9bf4b 100644 --- a/trunk/drivers/scsi/sata_mv.c +++ b/trunk/drivers/scsi/sata_mv.c @@ -374,6 +374,7 @@ static struct scsi_host_template mv_sht = { .dma_boundary = MV_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; static const struct ata_port_operations mv5_ops = { diff --git a/trunk/drivers/scsi/sata_nv.c b/trunk/drivers/scsi/sata_nv.c index c0cf52cb975a..4954896dfdb9 100644 --- a/trunk/drivers/scsi/sata_nv.c +++ b/trunk/drivers/scsi/sata_nv.c @@ -235,6 +235,7 @@ static struct scsi_host_template nv_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; static const struct ata_port_operations nv_ops = { diff --git a/trunk/drivers/scsi/sata_promise.c b/trunk/drivers/scsi/sata_promise.c index 3d1ea09a06a1..da7fa04b8a73 100644 --- a/trunk/drivers/scsi/sata_promise.c +++ b/trunk/drivers/scsi/sata_promise.c @@ -114,6 +114,7 @@ static struct scsi_host_template pdc_ata_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; static const struct ata_port_operations pdc_sata_ops = { diff --git a/trunk/drivers/scsi/sata_sil.c b/trunk/drivers/scsi/sata_sil.c index b017f85e6d6a..d2053487c73b 100644 --- a/trunk/drivers/scsi/sata_sil.c +++ b/trunk/drivers/scsi/sata_sil.c @@ -147,6 +147,7 @@ static struct scsi_host_template sil_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; static const struct ata_port_operations sil_ops = { diff --git a/trunk/drivers/scsi/sata_sil24.c b/trunk/drivers/scsi/sata_sil24.c index 923130185a9e..a0ad3ed2200a 100644 --- a/trunk/drivers/scsi/sata_sil24.c +++ b/trunk/drivers/scsi/sata_sil24.c @@ -292,6 +292,7 @@ static struct scsi_host_template sil24_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, /* NCQ not supported yet */ }; static const struct ata_port_operations sil24_ops = { diff --git a/trunk/drivers/scsi/sata_sis.c b/trunk/drivers/scsi/sata_sis.c index 2df8c5632ac3..32e12620b162 100644 --- a/trunk/drivers/scsi/sata_sis.c +++ b/trunk/drivers/scsi/sata_sis.c @@ -99,6 +99,7 @@ static struct scsi_host_template sis_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; static const struct ata_port_operations sis_ops = { diff --git a/trunk/drivers/scsi/sata_svw.c b/trunk/drivers/scsi/sata_svw.c index 668373590aa4..6e7f7c83a75a 100644 --- a/trunk/drivers/scsi/sata_svw.c +++ b/trunk/drivers/scsi/sata_svw.c @@ -303,6 +303,7 @@ static struct scsi_host_template k2_sata_sht = { .proc_info = k2_sata_proc_info, #endif .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; diff --git a/trunk/drivers/scsi/sata_sx4.c b/trunk/drivers/scsi/sata_sx4.c index bc87c16c80d2..94b253b80da8 100644 --- a/trunk/drivers/scsi/sata_sx4.c +++ b/trunk/drivers/scsi/sata_sx4.c @@ -194,6 +194,7 @@ static struct scsi_host_template pdc_sata_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; static const struct ata_port_operations pdc_20621_ops = { diff --git a/trunk/drivers/scsi/sata_uli.c b/trunk/drivers/scsi/sata_uli.c index 9635ca700977..b2422a0f25c8 100644 --- a/trunk/drivers/scsi/sata_uli.c +++ b/trunk/drivers/scsi/sata_uli.c @@ -87,6 +87,7 @@ static struct scsi_host_template uli_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; static const struct ata_port_operations uli_ops = { diff --git a/trunk/drivers/scsi/sata_via.c b/trunk/drivers/scsi/sata_via.c index 6d5b0a794cfd..c76215692da2 100644 --- a/trunk/drivers/scsi/sata_via.c +++ b/trunk/drivers/scsi/sata_via.c @@ -106,6 +106,7 @@ static struct scsi_host_template svia_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; static const struct ata_port_operations svia_sata_ops = { diff --git a/trunk/drivers/scsi/sata_vsc.c b/trunk/drivers/scsi/sata_vsc.c index 2e2c3b7acb0c..fcfa486965b4 100644 --- a/trunk/drivers/scsi/sata_vsc.c +++ b/trunk/drivers/scsi/sata_vsc.c @@ -235,6 +235,7 @@ static struct scsi_host_template vsc_sata_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .bios_param = ata_std_bios_param, + .ordered_flush = 1, }; diff --git a/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index ba93d6e66d48..a7f3f0c84db7 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/drivers/scsi/scsi_lib.c @@ -308,7 +308,7 @@ struct scsi_io_context { static kmem_cache_t *scsi_io_context_cache; -static void scsi_end_async(struct request *req, int uptodate) +static void scsi_end_async(struct request *req) { struct scsi_io_context *sioc = req->end_io_data; @@ -791,7 +791,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, spin_lock_irqsave(q->queue_lock, flags); if (blk_rq_tagged(req)) blk_queue_end_tag(q, req); - end_that_request_last(req, uptodate); + end_that_request_last(req); spin_unlock_irqrestore(q->queue_lock, flags); /* @@ -932,6 +932,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, int sense_valid = 0; int sense_deferred = 0; + if (blk_complete_barrier_rq(q, req, good_bytes >> 9)) + return; + /* * Free up any indirection buffers we allocated for DMA purposes. * For the case of a READ, we need to copy the data out of the @@ -1196,6 +1199,38 @@ static int scsi_init_io(struct scsi_cmnd *cmd) return BLKPREP_KILL; } +static int scsi_prepare_flush_fn(request_queue_t *q, struct request *rq) +{ + struct scsi_device *sdev = q->queuedata; + struct scsi_driver *drv; + + if (sdev->sdev_state == SDEV_RUNNING) { + drv = *(struct scsi_driver **) rq->rq_disk->private_data; + + if (drv->prepare_flush) + return drv->prepare_flush(q, rq); + } + + return 0; +} + +static void scsi_end_flush_fn(request_queue_t *q, struct request *rq) +{ + struct scsi_device *sdev = q->queuedata; + struct request *flush_rq = rq->end_io_data; + struct scsi_driver *drv; + + if (flush_rq->errors) { + printk("scsi: barrier error, disabling flush support\n"); + blk_queue_ordered(q, QUEUE_ORDERED_NONE); + } + + if (sdev->sdev_state == SDEV_RUNNING) { + drv = *(struct scsi_driver **) rq->rq_disk->private_data; + drv->end_flush(q, rq); + } +} + static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, sector_t *error_sector) { @@ -1668,6 +1703,17 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) blk_queue_segment_boundary(q, shost->dma_boundary); blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); + /* + * ordered tags are superior to flush ordering + */ + if (shost->ordered_tag) + blk_queue_ordered(q, QUEUE_ORDERED_TAG); + else if (shost->ordered_flush) { + blk_queue_ordered(q, QUEUE_ORDERED_FLUSH); + q->prepare_flush_fn = scsi_prepare_flush_fn; + q->end_flush_fn = scsi_end_flush_fn; + } + if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); return q; diff --git a/trunk/drivers/scsi/scsi_sysfs.c b/trunk/drivers/scsi/scsi_sysfs.c index ea7f3a433572..15842b1f0f4a 100644 --- a/trunk/drivers/scsi/scsi_sysfs.c +++ b/trunk/drivers/scsi/scsi_sysfs.c @@ -263,40 +263,9 @@ static int scsi_bus_match(struct device *dev, struct device_driver *gendrv) return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0; } -static int scsi_bus_suspend(struct device * dev, pm_message_t state) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct scsi_host_template *sht = sdev->host->hostt; - int err; - - err = scsi_device_quiesce(sdev); - if (err) - return err; - - if (sht->suspend) - err = sht->suspend(sdev); - - return err; -} - -static int scsi_bus_resume(struct device * dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct scsi_host_template *sht = sdev->host->hostt; - int err = 0; - - if (sht->resume) - err = sht->resume(sdev); - - scsi_device_resume(sdev); - return err; -} - struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, - .suspend = scsi_bus_suspend, - .resume = scsi_bus_resume, }; int scsi_sysfs_register(void) diff --git a/trunk/drivers/scsi/sd.c b/trunk/drivers/scsi/sd.c index 32d4d8d7b9f3..3d3ad7d1b779 100644 --- a/trunk/drivers/scsi/sd.c +++ b/trunk/drivers/scsi/sd.c @@ -102,7 +102,6 @@ struct scsi_disk { u8 write_prot; unsigned WCE : 1; /* state of disk WCE bit */ unsigned RCD : 1; /* state of disk RCD bit, unused */ - unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ }; static DEFINE_IDR(sd_index_idr); @@ -122,7 +121,8 @@ static void sd_shutdown(struct device *dev); static void sd_rescan(struct device *); static int sd_init_command(struct scsi_cmnd *); static int sd_issue_flush(struct device *, sector_t *); -static void sd_prepare_flush(request_queue_t *, struct request *); +static void sd_end_flush(request_queue_t *, struct request *); +static int sd_prepare_flush(request_queue_t *, struct request *); static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, unsigned char *buffer); @@ -137,6 +137,8 @@ static struct scsi_driver sd_template = { .rescan = sd_rescan, .init_command = sd_init_command, .issue_flush = sd_issue_flush, + .prepare_flush = sd_prepare_flush, + .end_flush = sd_end_flush, }; /* @@ -344,7 +346,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) if (block > 0xffffffff) { SCpnt->cmnd[0] += READ_16 - READ_6; - SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0; SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; @@ -364,7 +365,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) this_count = 0xffff; SCpnt->cmnd[0] += READ_10 - READ_6; - SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0; SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; @@ -373,17 +373,6 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; } else { - if (unlikely(blk_fua_rq(rq))) { - /* - * This happens only if this drive failed - * 10byte rw command with ILLEGAL_REQUEST - * during operation and thus turned off - * use_10_for_rw. - */ - printk(KERN_ERR "sd: FUA write on READ/WRITE(6) drive\n"); - return 0; - } - SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); SCpnt->cmnd[2] = (unsigned char) ((block >> 8) & 0xff); SCpnt->cmnd[3] = (unsigned char) block & 0xff; @@ -740,13 +729,42 @@ static int sd_issue_flush(struct device *dev, sector_t *error_sector) return ret; } -static void sd_prepare_flush(request_queue_t *q, struct request *rq) +static void sd_end_flush(request_queue_t *q, struct request *flush_rq) +{ + struct request *rq = flush_rq->end_io_data; + struct scsi_cmnd *cmd = rq->special; + unsigned int bytes = rq->hard_nr_sectors << 9; + + if (!flush_rq->errors) { + spin_unlock(q->queue_lock); + scsi_io_completion(cmd, bytes, 0); + spin_lock(q->queue_lock); + } else if (blk_barrier_postflush(rq)) { + spin_unlock(q->queue_lock); + scsi_io_completion(cmd, 0, bytes); + spin_lock(q->queue_lock); + } else { + /* + * force journal abort of barriers + */ + end_that_request_first(rq, -EOPNOTSUPP, rq->hard_nr_sectors); + end_that_request_last(rq); + } +} + +static int sd_prepare_flush(request_queue_t *q, struct request *rq) { + struct scsi_device *sdev = q->queuedata; + struct scsi_disk *sdkp = dev_get_drvdata(&sdev->sdev_gendev); + + if (!sdkp || !sdkp->WCE) + return 0; + memset(rq->cmd, 0, sizeof(rq->cmd)); - rq->flags |= REQ_BLOCK_PC; + rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER; rq->timeout = SD_TIMEOUT; rq->cmd[0] = SYNCHRONIZE_CACHE; - rq->cmd_len = 10; + return 1; } static void sd_rescan(struct device *dev) @@ -1409,18 +1427,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, sdkp->RCD = 0; } - sdkp->DPOFUA = (data.device_specific & 0x10) != 0; - if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) { - printk(KERN_NOTICE "SCSI device %s: uses " - "READ/WRITE(6), disabling FUA\n", diskname); - sdkp->DPOFUA = 0; - } - ct = sdkp->RCD + 2*sdkp->WCE; - printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n", - diskname, types[ct], - sdkp->DPOFUA ? " w/ FUA" : ""); + printk(KERN_NOTICE "SCSI device %s: drive cache: %s\n", + diskname, types[ct]); return; } @@ -1452,7 +1462,6 @@ static int sd_revalidate_disk(struct gendisk *disk) struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; unsigned char *buffer; - unsigned ordered; SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name)); @@ -1489,21 +1498,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_write_protect_flag(sdkp, disk->disk_name, buffer); sd_read_cache_type(sdkp, disk->disk_name, buffer); } - - /* - * We now have all cache related info, determine how we deal - * with ordered requests. Note that as the current SCSI - * dispatch function can alter request order, we cannot use - * QUEUE_ORDERED_TAG_* even when ordered tag is supported. - */ - if (sdkp->WCE) - ordered = sdkp->DPOFUA - ? QUEUE_ORDERED_DRAIN_FUA : QUEUE_ORDERED_DRAIN_FLUSH; - else - ordered = QUEUE_ORDERED_DRAIN; - - blk_queue_ordered(sdkp->disk->queue, ordered, sd_prepare_flush); - + set_capacity(disk, sdkp->capacity); kfree(buffer); @@ -1603,7 +1598,6 @@ static int sd_probe(struct device *dev) strcpy(gd->devfs_name, sdp->devfs_name); gd->private_data = &sdkp->driver; - gd->queue = sdkp->device->request_queue; sd_revalidate_disk(gd); @@ -1611,6 +1605,7 @@ static int sd_probe(struct device *dev) gd->flags = GENHD_FL_DRIVERFS; if (sdp->removable) gd->flags |= GENHD_FL_REMOVABLE; + gd->queue = sdkp->device->request_queue; dev_set_drvdata(dev, sdkp); add_disk(gd); diff --git a/trunk/drivers/serial/mpc52xx_uart.c b/trunk/drivers/serial/mpc52xx_uart.c index 1288d6203e94..b8727d9bf690 100644 --- a/trunk/drivers/serial/mpc52xx_uart.c +++ b/trunk/drivers/serial/mpc52xx_uart.c @@ -37,11 +37,11 @@ * by the bootloader or in the platform init code. * * The idx field must be equal to the PSC index ( e.g. 0 for PSC1, 1 for PSC2, - * and so on). So the PSC1 is mapped to /dev/ttyPSC0, PSC2 to /dev/ttyPSC1 and - * so on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly - * fpr the console code : without this 1:1 mapping, at early boot time, when we - * are parsing the kernel args console=ttyPSC?, we wouldn't know wich PSC it - * will be mapped to. + * and so on). So the PSC1 is mapped to /dev/ttyS0, PSC2 to /dev/ttyS1 and so + * on. But be warned, it's an ABSOLUTE REQUIREMENT ! This is needed mainly for + * the console code : without this 1:1 mapping, at early boot time, when we are + * parsing the kernel args console=ttyS?, we wouldn't know wich PSC it will be + * mapped to. */ #include @@ -65,10 +65,6 @@ #include -/* We've been assigned a range on the "Low-density serial ports" major */ -#define SERIAL_PSC_MAJOR 204 -#define SERIAL_PSC_MINOR 148 - #define ISR_PASS_LIMIT 256 /* Max number of iteration in the interrupt */ @@ -672,15 +668,15 @@ mpc52xx_console_setup(struct console *co, char *options) } -static struct uart_driver mpc52xx_uart_driver; +extern struct uart_driver mpc52xx_uart_driver; static struct console mpc52xx_console = { - .name = "ttyPSC", + .name = "ttyS", .write = mpc52xx_console_write, .device = uart_console_device, .setup = mpc52xx_console_setup, .flags = CON_PRINTBUFFER, - .index = -1, /* Specified on the cmdline (e.g. console=ttyPSC0 ) */ + .index = -1, /* Specified on the cmdline (e.g. console=ttyS0 ) */ .data = &mpc52xx_uart_driver, }; @@ -707,10 +703,10 @@ console_initcall(mpc52xx_console_init); static struct uart_driver mpc52xx_uart_driver = { .owner = THIS_MODULE, .driver_name = "mpc52xx_psc_uart", - .dev_name = "ttyPSC", - .devfs_name = "ttyPSC", - .major = SERIAL_PSC_MAJOR, - .minor = SERIAL_PSC_MINOR, + .dev_name = "ttyS", + .devfs_name = "ttyS", + .major = TTY_MAJOR, + .minor = 64, .nr = MPC52xx_PSC_MAXNUM, .cons = MPC52xx_PSC_CONSOLE, }; diff --git a/trunk/fs/bio.c b/trunk/fs/bio.c index dfe242a21eb4..38d3e8023a07 100644 --- a/trunk/fs/bio.c +++ b/trunk/fs/bio.c @@ -325,31 +325,10 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page if (unlikely(bio_flagged(bio, BIO_CLONED))) return 0; - if (((bio->bi_size + len) >> 9) > max_sectors) + if (bio->bi_vcnt >= bio->bi_max_vecs) return 0; - /* - * For filesystems with a blocksize smaller than the pagesize - * we will often be called with the same page as last time and - * a consecutive offset. Optimize this special case. - */ - if (bio->bi_vcnt > 0) { - struct bio_vec *prev = &bio->bi_io_vec[bio->bi_vcnt - 1]; - - if (page == prev->bv_page && - offset == prev->bv_offset + prev->bv_len) { - prev->bv_len += len; - if (q->merge_bvec_fn && - q->merge_bvec_fn(q, bio, prev) < len) { - prev->bv_len -= len; - return 0; - } - - goto done; - } - } - - if (bio->bi_vcnt >= bio->bi_max_vecs) + if (((bio->bi_size + len) >> 9) > max_sectors) return 0; /* @@ -403,7 +382,6 @@ static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page bio->bi_vcnt++; bio->bi_phys_segments++; bio->bi_hw_segments++; - done: bio->bi_size += len; return len; } diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index e75a9548da8e..22533cce0611 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -324,7 +324,7 @@ void install_arg_page(struct vm_area_struct *vma, lru_cache_add_active(page); set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte( page, vma->vm_page_prot)))); - page_add_new_anon_rmap(page, vma, address); + page_add_anon_rmap(page, vma, address); pte_unmap_unlock(pte, ptl); /* no need for flush_tlb */ diff --git a/trunk/fs/fuse/dev.c b/trunk/fs/fuse/dev.c index e08ab4702d97..8f873e621f41 100644 --- a/trunk/fs/fuse/dev.c +++ b/trunk/fs/fuse/dev.c @@ -148,26 +148,6 @@ void fuse_release_background(struct fuse_req *req) spin_unlock(&fuse_lock); } -static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) -{ - int i; - struct fuse_init_out *arg = &req->misc.init_out; - - if (arg->major != FUSE_KERNEL_VERSION) - fc->conn_error = 1; - else { - fc->minor = arg->minor; - fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; - } - - /* After INIT reply is received other requests can go - out. So do (FUSE_MAX_OUTSTANDING - 1) number of - up()s on outstanding_sem. The last up() is done in - fuse_putback_request() */ - for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) - up(&fc->outstanding_sem); -} - /* * This function is called when a request is finished. Either a reply * has arrived or it was interrupted (and not yet sent) or some error @@ -192,9 +172,19 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) up_read(&fc->sbput_sem); } wake_up(&req->waitq); - if (req->in.h.opcode == FUSE_INIT) - process_init_reply(fc, req); - else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { + if (req->in.h.opcode == FUSE_INIT) { + int i; + + if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION) + fc->conn_error = 1; + + /* After INIT reply is received other requests can go + out. So do (FUSE_MAX_OUTSTANDING - 1) number of + up()s on outstanding_sem. The last up() is done in + fuse_putback_request() */ + for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) + up(&fc->outstanding_sem); + } else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { /* Special case for failed iget in CREATE */ u64 nodeid = req->in.h.nodeid; __fuse_get_request(req); @@ -367,7 +357,7 @@ void fuse_send_init(struct fuse_conn *fc) /* This is called from fuse_read_super() so there's guaranteed to be a request available */ struct fuse_req *req = do_get_request(fc); - struct fuse_init_in *arg = &req->misc.init_in; + struct fuse_init_in_out *arg = &req->misc.init_in_out; arg->major = FUSE_KERNEL_VERSION; arg->minor = FUSE_KERNEL_MINOR_VERSION; req->in.h.opcode = FUSE_INIT; @@ -375,12 +365,8 @@ void fuse_send_init(struct fuse_conn *fc) req->in.args[0].size = sizeof(*arg); req->in.args[0].value = arg; req->out.numargs = 1; - /* Variable length arguement used for backward compatibility - with interface version < 7.5. Rest of init_out is zeroed - by do_get_request(), so a short reply is not a problem */ - req->out.argvar = 1; - req->out.args[0].size = sizeof(struct fuse_init_out); - req->out.args[0].value = &req->misc.init_out; + req->out.args[0].size = sizeof(*arg); + req->out.args[0].value = arg; request_send_background(fc, req); } @@ -629,7 +615,6 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, struct fuse_copy_state cs; unsigned reqsize; - restart: spin_lock(&fuse_lock); fc = file->private_data; err = -EPERM; @@ -645,25 +630,20 @@ static ssize_t fuse_dev_readv(struct file *file, const struct iovec *iov, req = list_entry(fc->pending.next, struct fuse_req, list); list_del_init(&req->list); + spin_unlock(&fuse_lock); in = &req->in; - reqsize = in->h.len; - /* If request is too large, reply with an error and restart the read */ - if (iov_length(iov, nr_segs) < reqsize) { - req->out.h.error = -EIO; - /* SETXATTR is special, since it may contain too large data */ - if (in->h.opcode == FUSE_SETXATTR) - req->out.h.error = -E2BIG; - request_end(fc, req); - goto restart; - } - spin_unlock(&fuse_lock); + reqsize = req->in.h.len; fuse_copy_init(&cs, 1, req, iov, nr_segs); - err = fuse_copy_one(&cs, &in->h, sizeof(in->h)); - if (!err) - err = fuse_copy_args(&cs, in->numargs, in->argpages, - (struct fuse_arg *) in->args, 0); + err = -EINVAL; + if (iov_length(iov, nr_segs) >= reqsize) { + err = fuse_copy_one(&cs, &in->h, sizeof(in->h)); + if (!err) + err = fuse_copy_args(&cs, in->numargs, in->argpages, + (struct fuse_arg *) in->args, 0); + } fuse_copy_finish(&cs); + spin_lock(&fuse_lock); req->locked = 0; if (!err && req->interrupted) diff --git a/trunk/fs/fuse/dir.c b/trunk/fs/fuse/dir.c index 417bcee466f6..51f5da652771 100644 --- a/trunk/fs/fuse/dir.c +++ b/trunk/fs/fuse/dir.c @@ -13,16 +13,8 @@ #include #include #include +#include -/* - * FUSE caches dentries and attributes with separate timeout. The - * time in jiffies until the dentry/attributes are valid is stored in - * dentry->d_time and fuse_inode->i_time respectively. - */ - -/* - * Calculate the time in jiffies until a dentry/attributes are valid - */ static inline unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) { @@ -30,50 +22,6 @@ static inline unsigned long time_to_jiffies(unsigned long sec, return jiffies + timespec_to_jiffies(&ts); } -/* - * Set dentry and possibly attribute timeouts from the lookup/mk* - * replies - */ -static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) -{ - entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec); - if (entry->d_inode) - get_fuse_inode(entry->d_inode)->i_time = - time_to_jiffies(o->attr_valid, o->attr_valid_nsec); -} - -/* - * Mark the attributes as stale, so that at the next call to - * ->getattr() they will be fetched from userspace - */ -void fuse_invalidate_attr(struct inode *inode) -{ - get_fuse_inode(inode)->i_time = jiffies - 1; -} - -/* - * Just mark the entry as stale, so that a next attempt to look it up - * will result in a new lookup call to userspace - * - * This is called when a dentry is about to become negative and the - * timeout is unknown (unlink, rmdir, rename and in some cases - * lookup) - */ -static void fuse_invalidate_entry_cache(struct dentry *entry) -{ - entry->d_time = jiffies - 1; -} - -/* - * Same as fuse_invalidate_entry_cache(), but also try to remove the - * dentry from the hash - */ -static void fuse_invalidate_entry(struct dentry *entry) -{ - d_invalidate(entry); - fuse_invalidate_entry_cache(entry); -} - static void fuse_lookup_init(struct fuse_req *req, struct inode *dir, struct dentry *entry, struct fuse_entry_out *outarg) @@ -89,34 +37,17 @@ static void fuse_lookup_init(struct fuse_req *req, struct inode *dir, req->out.args[0].value = outarg; } -/* - * Check whether the dentry is still valid - * - * If the entry validity timeout has expired and the dentry is - * positive, try to redo the lookup. If the lookup results in a - * different inode, then let the VFS invalidate the dentry and redo - * the lookup once more. If the lookup results in the same inode, - * then refresh the attributes, timeouts and mark the dentry valid. - */ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) { - struct inode *inode = entry->d_inode; - - if (inode && is_bad_inode(inode)) + if (!entry->d_inode || is_bad_inode(entry->d_inode)) return 0; else if (time_after(jiffies, entry->d_time)) { int err; struct fuse_entry_out outarg; - struct fuse_conn *fc; - struct fuse_req *req; - - /* Doesn't hurt to "reset" the validity timeout */ - fuse_invalidate_entry_cache(entry); - if (!inode) - return 0; - - fc = get_fuse_conn(inode); - req = fuse_get_request(fc); + struct inode *inode = entry->d_inode; + struct fuse_inode *fi = get_fuse_inode(inode); + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_req *req = fuse_get_request(fc); if (!req) return 0; @@ -124,7 +55,6 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) request_send(fc, req); err = req->out.h.error; if (!err) { - struct fuse_inode *fi = get_fuse_inode(inode); if (outarg.nodeid != get_node_id(inode)) { fuse_send_forget(fc, req, outarg.nodeid, 1); return 0; @@ -136,18 +66,18 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) return 0; fuse_change_attributes(inode, &outarg.attr); - fuse_change_timeout(entry, &outarg); + entry->d_time = time_to_jiffies(outarg.entry_valid, + outarg.entry_valid_nsec); + fi->i_time = time_to_jiffies(outarg.attr_valid, + outarg.attr_valid_nsec); } return 1; } -/* - * Check if there's already a hashed alias of this directory inode. - * If yes, then lookup and mkdir must not create a new alias. - */ static int dir_alias(struct inode *inode) { if (S_ISDIR(inode->i_mode)) { + /* Don't allow creating an alias to a directory */ struct dentry *alias = d_find_alias(inode); if (alias) { dput(alias); @@ -166,14 +96,8 @@ static struct dentry_operations fuse_dentry_operations = { .d_revalidate = fuse_dentry_revalidate, }; -static inline int valid_mode(int m) -{ - return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || - S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); -} - -static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, - struct nameidata *nd) +static int fuse_lookup_iget(struct inode *dir, struct dentry *entry, + struct inode **inodep) { int err; struct fuse_entry_out outarg; @@ -182,49 +106,53 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, struct fuse_req *req; if (entry->d_name.len > FUSE_NAME_MAX) - return ERR_PTR(-ENAMETOOLONG); + return -ENAMETOOLONG; req = fuse_get_request(fc); if (!req) - return ERR_PTR(-EINTR); + return -EINTR; fuse_lookup_init(req, dir, entry, &outarg); request_send(fc, req); err = req->out.h.error; - if (!err && ((outarg.nodeid && invalid_nodeid(outarg.nodeid)) || - !valid_mode(outarg.attr.mode))) + if (!err && invalid_nodeid(outarg.nodeid)) err = -EIO; - if (!err && outarg.nodeid) { + if (!err) { inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, &outarg.attr); if (!inode) { fuse_send_forget(fc, req, outarg.nodeid, 1); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } } fuse_put_request(fc, req); if (err && err != -ENOENT) - return ERR_PTR(err); + return err; - if (inode && dir_alias(inode)) { - iput(inode); - return ERR_PTR(-EIO); + if (inode) { + struct fuse_inode *fi = get_fuse_inode(inode); + entry->d_time = time_to_jiffies(outarg.entry_valid, + outarg.entry_valid_nsec); + fi->i_time = time_to_jiffies(outarg.attr_valid, + outarg.attr_valid_nsec); } - d_add(entry, inode); + entry->d_op = &fuse_dentry_operations; - if (!err) - fuse_change_timeout(entry, &outarg); - else - fuse_invalidate_entry_cache(entry); - return NULL; + *inodep = inode; + return 0; +} + +void fuse_invalidate_attr(struct inode *inode) +{ + get_fuse_inode(inode)->i_time = jiffies - 1; +} + +static void fuse_invalidate_entry(struct dentry *entry) +{ + d_invalidate(entry); + entry->d_time = jiffies - 1; } -/* - * Atomic create+open operation - * - * If the filesystem doesn't support this, then fall back to separate - * 'mknod' + 'open' requests. - */ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, struct nameidata *nd) { @@ -235,6 +163,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, struct fuse_open_in inarg; struct fuse_open_out outopen; struct fuse_entry_out outentry; + struct fuse_inode *fi; struct fuse_file *ff; struct file *file; int flags = nd->intent.open.flags - 1; @@ -243,6 +172,10 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, if (fc->no_create) goto out; + err = -ENAMETOOLONG; + if (entry->d_name.len > FUSE_NAME_MAX) + goto out; + err = -EINTR; req = fuse_get_request(fc); if (!req) @@ -287,15 +220,17 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, if (!inode) { flags &= ~(O_CREAT | O_EXCL | O_TRUNC); ff->fh = outopen.fh; - /* Special release, with inode = NULL, this will - trigger a 'forget' request when the release is - complete */ fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0); goto out_put_request; } fuse_put_request(fc, req); + entry->d_time = time_to_jiffies(outentry.entry_valid, + outentry.entry_valid_nsec); + fi = get_fuse_inode(inode); + fi->i_time = time_to_jiffies(outentry.attr_valid, + outentry.attr_valid_nsec); + d_instantiate(entry, inode); - fuse_change_timeout(entry, &outentry); file = lookup_instantiate_filp(nd, entry, generic_file_open); if (IS_ERR(file)) { ff->fh = outopen.fh; @@ -313,15 +248,13 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, return err; } -/* - * Code shared between mknod, mkdir, symlink and link - */ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, struct inode *dir, struct dentry *entry, int mode) { struct fuse_entry_out outarg; struct inode *inode; + struct fuse_inode *fi; int err; req->in.h.nodeid = get_node_id(dir); @@ -335,13 +268,10 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, fuse_put_request(fc, req); return err; } - err = -EIO; - if (invalid_nodeid(outarg.nodeid)) - goto out_put_request; - - if ((outarg.attr.mode ^ mode) & S_IFMT) - goto out_put_request; - + if (invalid_nodeid(outarg.nodeid)) { + fuse_put_request(fc, req); + return -EIO; + } inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, &outarg.attr); if (!inode) { @@ -350,19 +280,22 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, } fuse_put_request(fc, req); - if (dir_alias(inode)) { + /* Don't allow userspace to do really stupid things... */ + if (((inode->i_mode ^ mode) & S_IFMT) || dir_alias(inode)) { iput(inode); return -EIO; } + entry->d_time = time_to_jiffies(outarg.entry_valid, + outarg.entry_valid_nsec); + + fi = get_fuse_inode(inode); + fi->i_time = time_to_jiffies(outarg.attr_valid, + outarg.attr_valid_nsec); + d_instantiate(entry, inode); - fuse_change_timeout(entry, &outarg); fuse_invalidate_attr(dir); return 0; - - out_put_request: - fuse_put_request(fc, req); - return err; } static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, @@ -422,7 +355,12 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, { struct fuse_conn *fc = get_fuse_conn(dir); unsigned len = strlen(link) + 1; - struct fuse_req *req = fuse_get_request(fc); + struct fuse_req *req; + + if (len > FUSE_SYMLINK_MAX) + return -ENAMETOOLONG; + + req = fuse_get_request(fc); if (!req) return -EINTR; @@ -461,7 +399,6 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) inode->i_nlink = 0; fuse_invalidate_attr(inode); fuse_invalidate_attr(dir); - fuse_invalidate_entry_cache(entry); } else if (err == -EINTR) fuse_invalidate_entry(entry); return err; @@ -487,7 +424,6 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) if (!err) { entry->d_inode->i_nlink = 0; fuse_invalidate_attr(dir); - fuse_invalidate_entry_cache(entry); } else if (err == -EINTR) fuse_invalidate_entry(entry); return err; @@ -523,10 +459,6 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, fuse_invalidate_attr(olddir); if (olddir != newdir) fuse_invalidate_attr(newdir); - - /* newent will end up negative */ - if (newent->d_inode) - fuse_invalidate_entry_cache(newent); } else if (err == -EINTR) { /* If request was interrupted, DEITY only knows if the rename actually took place. If the invalidation @@ -634,15 +566,6 @@ static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task) return 0; } -/* - * Check whether the inode attributes are still valid - * - * If the attribute validity timeout has expired, then fetch the fresh - * attributes with a 'getattr' request - * - * I'm not sure why cached attributes are never returned for the root - * inode, this is probably being too cautious. - */ static int fuse_revalidate(struct dentry *entry) { struct inode *inode = entry->d_inode; @@ -690,19 +613,6 @@ static int fuse_access(struct inode *inode, int mask) return err; } -/* - * Check permission. The two basic access models of FUSE are: - * - * 1) Local access checking ('default_permissions' mount option) based - * on file mode. This is the plain old disk filesystem permission - * modell. - * - * 2) "Remote" access checking, where server is responsible for - * checking permission in each inode operation. An exception to this - * is if ->permission() was invoked from sys_access() in which case an - * access request is sent. Execute permission is still checked - * locally based on file mode. - */ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) { struct fuse_conn *fc = get_fuse_conn(inode); @@ -721,10 +631,14 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) err = generic_permission(inode, mask, NULL); } - /* Note: the opposite of the above test does not - exist. So if permissions are revoked this won't be - noticed immediately, only after the attribute - timeout has expired */ + /* FIXME: Need some mechanism to revoke permissions: + currently if the filesystem suddenly changes the + file mode, we will not be informed about it, and + continue to allow access to the file/directory. + + This is actually not so grave, since the user can + simply keep access to the file/directory anyway by + keeping it open... */ return err; } else { @@ -777,12 +691,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) struct page *page; struct inode *inode = file->f_dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_req *req; - - if (is_bad_inode(inode)) - return -EIO; - - req = fuse_get_request(fc); + struct fuse_req *req = fuse_get_request(fc); if (!req) return -EINTR; @@ -897,15 +806,6 @@ static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) } } -/* - * Set attributes, and at the same time refresh them. - * - * Truncation is slightly complicated, because the 'truncate' request - * may fail, in which case we don't want to touch the mapping. - * vmtruncate() doesn't allow for this case. So do the rlimit - * checking by hand and call vmtruncate() only after the file has - * actually been truncated. - */ static int fuse_setattr(struct dentry *entry, struct iattr *attr) { struct inode *inode = entry->d_inode; @@ -983,6 +883,23 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, return err; } +static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, + struct nameidata *nd) +{ + struct inode *inode; + int err; + + err = fuse_lookup_iget(dir, entry, &inode); + if (err) + return ERR_PTR(err); + if (inode && dir_alias(inode)) { + iput(inode); + return ERR_PTR(-EIO); + } + d_add(entry, inode); + return NULL; +} + static int fuse_setxattr(struct dentry *entry, const char *name, const void *value, size_t size, int flags) { @@ -992,6 +909,9 @@ static int fuse_setxattr(struct dentry *entry, const char *name, struct fuse_setxattr_in inarg; int err; + if (size > FUSE_XATTR_SIZE_MAX) + return -E2BIG; + if (fc->no_setxattr) return -EOPNOTSUPP; diff --git a/trunk/fs/fuse/file.c b/trunk/fs/fuse/file.c index 05dedddf4289..2ca86141d13a 100644 --- a/trunk/fs/fuse/file.c +++ b/trunk/fs/fuse/file.c @@ -163,9 +163,6 @@ static int fuse_flush(struct file *file) struct fuse_flush_in inarg; int err; - if (is_bad_inode(inode)) - return -EIO; - if (fc->no_flush) return 0; @@ -202,9 +199,6 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync, struct fuse_fsync_in inarg; int err; - if (is_bad_inode(inode)) - return -EIO; - if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) return 0; @@ -278,22 +272,16 @@ static int fuse_readpage(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_req *req; - int err; - - err = -EIO; - if (is_bad_inode(inode)) - goto out; - - err = -EINTR; - req = fuse_get_request(fc); + loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT; + struct fuse_req *req = fuse_get_request(fc); + int err = -EINTR; if (!req) goto out; req->out.page_zeroing = 1; req->num_pages = 1; req->pages[0] = page; - fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE); + fuse_send_read(req, file, inode, pos, PAGE_CACHE_SIZE); err = req->out.h.error; fuse_put_request(fc, req); if (!err) @@ -307,7 +295,7 @@ static int fuse_readpage(struct file *file, struct page *page) static int fuse_send_readpages(struct fuse_req *req, struct file *file, struct inode *inode) { - loff_t pos = page_offset(req->pages[0]); + loff_t pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT; size_t count = req->num_pages << PAGE_CACHE_SHIFT; unsigned i; req->out.page_zeroing = 1; @@ -357,10 +345,6 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_readpages_data data; int err; - - if (is_bad_inode(inode)) - return -EIO; - data.file = file; data.inode = inode; data.req = fuse_get_request(fc); @@ -418,13 +402,8 @@ static int fuse_commit_write(struct file *file, struct page *page, unsigned count = to - offset; struct inode *inode = page->mapping->host; struct fuse_conn *fc = get_fuse_conn(inode); - loff_t pos = page_offset(page) + offset; - struct fuse_req *req; - - if (is_bad_inode(inode)) - return -EIO; - - req = fuse_get_request(fc); + loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset; + struct fuse_req *req = fuse_get_request(fc); if (!req) return -EINTR; @@ -475,7 +454,7 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT); npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; - npages = min(max(npages, 1), FUSE_MAX_PAGES_PER_REQ); + npages = min(npages, FUSE_MAX_PAGES_PER_REQ); down_read(¤t->mm->mmap_sem); npages = get_user_pages(current, current->mm, user_addr, npages, write, 0, req->pages, NULL); @@ -496,16 +475,12 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, size_t nmax = write ? fc->max_write : fc->max_read; loff_t pos = *ppos; ssize_t res = 0; - struct fuse_req *req; - - if (is_bad_inode(inode)) - return -EIO; - - req = fuse_get_request(fc); + struct fuse_req *req = fuse_get_request(fc); if (!req) return -EINTR; while (count) { + size_t tmp; size_t nres; size_t nbytes = min(count, nmax); int err = fuse_get_user_pages(req, buf, nbytes, !write); @@ -513,8 +488,8 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, res = err; break; } - nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; - nbytes = min(count, nbytes); + tmp = (req->num_pages << PAGE_SHIFT) - req->page_offset; + nbytes = min(nbytes, tmp); if (write) nres = fuse_send_write(req, file, inode, pos, nbytes); else diff --git a/trunk/fs/fuse/fuse_i.h b/trunk/fs/fuse/fuse_i.h index 74c8d098a14a..0ea5301f86be 100644 --- a/trunk/fs/fuse/fuse_i.h +++ b/trunk/fs/fuse/fuse_i.h @@ -21,9 +21,6 @@ /** If more requests are outstanding, then the operation will block */ #define FUSE_MAX_OUTSTANDING 10 -/** It could be as large as PATH_MAX, but would that have any uses? */ -#define FUSE_NAME_MAX 1024 - /** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem module will check permissions based on the file mode. Otherwise no permission checking is done in the kernel */ @@ -111,6 +108,9 @@ struct fuse_out { struct fuse_arg args[3]; }; +struct fuse_req; +struct fuse_conn; + /** * A request to the client */ @@ -159,8 +159,7 @@ struct fuse_req { union { struct fuse_forget_in forget_in; struct fuse_release_in release_in; - struct fuse_init_in init_in; - struct fuse_init_out init_out; + struct fuse_init_in_out init_in_out; } misc; /** page vector */ @@ -273,9 +272,6 @@ struct fuse_conn { /** Is create not implemented by fs? */ unsigned no_create : 1; - /** Negotiated minor version */ - unsigned minor; - /** Backing dev info */ struct backing_dev_info bdi; }; diff --git a/trunk/fs/fuse/inode.c b/trunk/fs/fuse/inode.c index 04c80cc957a3..e69a546844d0 100644 --- a/trunk/fs/fuse/inode.c +++ b/trunk/fs/fuse/inode.c @@ -135,8 +135,12 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) fuse_init_common(inode); init_special_inode(inode, inode->i_mode, new_decode_dev(attr->rdev)); - } else - BUG(); + } else { + /* Don't let user create weird files */ + inode->i_mode = S_IFREG; + fuse_init_common(inode); + fuse_init_file_inode(inode); + } } static int fuse_inode_eq(struct inode *inode, void *_nodeidp) @@ -214,7 +218,6 @@ static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr { stbuf->f_type = FUSE_SUPER_MAGIC; stbuf->f_bsize = attr->bsize; - stbuf->f_frsize = attr->frsize; stbuf->f_blocks = attr->blocks; stbuf->f_bfree = attr->bfree; stbuf->f_bavail = attr->bavail; @@ -235,12 +238,10 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf) if (!req) return -EINTR; - memset(&outarg, 0, sizeof(outarg)); req->in.numargs = 0; req->in.h.opcode = FUSE_STATFS; req->out.numargs = 1; - req->out.args[0].size = - fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg); + req->out.args[0].size = sizeof(outarg); req->out.args[0].value = &outarg; request_send(fc, req); err = req->out.h.error; @@ -481,6 +482,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) fc->max_read = d.max_read; if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; + fc->max_write = FUSE_MAX_IN / 2; err = -ENOMEM; root = get_root_inode(sb, d.rootmode); diff --git a/trunk/fs/hfsplus/super.c b/trunk/fs/hfsplus/super.c index 6daaf7c755a6..8093351bd7c3 100644 --- a/trunk/fs/hfsplus/super.c +++ b/trunk/fs/hfsplus/super.c @@ -320,7 +320,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) /* temporarily use utf8 to correctly find the hidden dir below */ nls = sbi->nls; sbi->nls = load_nls("utf8"); - if (!sbi->nls) { + if (!nls) { printk("HFS+: unable to load nls for utf8\n"); err = -EINVAL; goto cleanup; diff --git a/trunk/fs/hugetlbfs/inode.c b/trunk/fs/hugetlbfs/inode.c index 8c41315a6e42..8c1cef3bb677 100644 --- a/trunk/fs/hugetlbfs/inode.c +++ b/trunk/fs/hugetlbfs/inode.c @@ -100,6 +100,9 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) loff_t len, vma_len; int ret; + if ((vma->vm_flags & (VM_MAYSHARE | VM_WRITE)) == VM_WRITE) + return -EINVAL; + if (vma->vm_pgoff & (HPAGE_SIZE / PAGE_SIZE - 1)) return -EINVAL; diff --git a/trunk/fs/jbd/checkpoint.c b/trunk/fs/jbd/checkpoint.c index cb3cef525c3b..014a51fd00d7 100644 --- a/trunk/fs/jbd/checkpoint.c +++ b/trunk/fs/jbd/checkpoint.c @@ -24,75 +24,29 @@ #include /* - * Unlink a buffer from a transaction checkpoint list. + * Unlink a buffer from a transaction. * * Called with j_list_lock held. */ -static void __buffer_unlink_first(struct journal_head *jh) +static inline void __buffer_unlink(struct journal_head *jh) { transaction_t *transaction; transaction = jh->b_cp_transaction; + jh->b_cp_transaction = NULL; jh->b_cpnext->b_cpprev = jh->b_cpprev; jh->b_cpprev->b_cpnext = jh->b_cpnext; - if (transaction->t_checkpoint_list == jh) { + if (transaction->t_checkpoint_list == jh) transaction->t_checkpoint_list = jh->b_cpnext; - if (transaction->t_checkpoint_list == jh) - transaction->t_checkpoint_list = NULL; - } -} - -/* - * Unlink a buffer from a transaction checkpoint(io) list. - * - * Called with j_list_lock held. - */ - -static inline void __buffer_unlink(struct journal_head *jh) -{ - transaction_t *transaction; - - transaction = jh->b_cp_transaction; - - __buffer_unlink_first(jh); - if (transaction->t_checkpoint_io_list == jh) { - transaction->t_checkpoint_io_list = jh->b_cpnext; - if (transaction->t_checkpoint_io_list == jh) - transaction->t_checkpoint_io_list = NULL; - } -} - -/* - * Move a buffer from the checkpoint list to the checkpoint io list - * - * Called with j_list_lock held - */ - -static inline void __buffer_relink_io(struct journal_head *jh) -{ - transaction_t *transaction; - - transaction = jh->b_cp_transaction; - __buffer_unlink_first(jh); - - if (!transaction->t_checkpoint_io_list) { - jh->b_cpnext = jh->b_cpprev = jh; - } else { - jh->b_cpnext = transaction->t_checkpoint_io_list; - jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev; - jh->b_cpprev->b_cpnext = jh; - jh->b_cpnext->b_cpprev = jh; - } - transaction->t_checkpoint_io_list = jh; + if (transaction->t_checkpoint_list == jh) + transaction->t_checkpoint_list = NULL; } /* * Try to release a checkpointed buffer from its transaction. - * Returns 1 if we released it and 2 if we also released the - * whole transaction. - * + * Returns 1 if we released it. * Requires j_list_lock * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it */ @@ -103,11 +57,12 @@ static int __try_to_free_cp_buf(struct journal_head *jh) if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { JBUFFER_TRACE(jh, "remove from checkpoint list"); - ret = __journal_remove_checkpoint(jh) + 1; + __journal_remove_checkpoint(jh); jbd_unlock_bh_state(bh); journal_remove_journal_head(bh); BUFFER_TRACE(bh, "release"); __brelse(bh); + ret = 1; } else { jbd_unlock_bh_state(bh); } @@ -162,53 +117,83 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh) } /* - * Clean up transaction's list of buffers submitted for io. - * We wait for any pending IO to complete and remove any clean - * buffers. Note that we take the buffers in the opposite ordering - * from the one in which they were submitted for IO. + * Clean up a transaction's checkpoint list. + * + * We wait for any pending IO to complete and make sure any clean + * buffers are removed from the transaction. + * + * Return 1 if we performed any actions which might have destroyed the + * checkpoint. (journal_remove_checkpoint() deletes the transaction when + * the last checkpoint buffer is cleansed) * * Called with j_list_lock held. */ - -static void __wait_cp_io(journal_t *journal, transaction_t *transaction) +static int __cleanup_transaction(journal_t *journal, transaction_t *transaction) { - struct journal_head *jh; + struct journal_head *jh, *next_jh, *last_jh; struct buffer_head *bh; - tid_t this_tid; - int released = 0; - - this_tid = transaction->t_tid; -restart: - /* Didn't somebody clean up the transaction in the meanwhile */ - if (journal->j_checkpoint_transactions != transaction || - transaction->t_tid != this_tid) - return; - while (!released && transaction->t_checkpoint_io_list) { - jh = transaction->t_checkpoint_io_list; + int ret = 0; + + assert_spin_locked(&journal->j_list_lock); + jh = transaction->t_checkpoint_list; + if (!jh) + return 0; + + last_jh = jh->b_cpprev; + next_jh = jh; + do { + jh = next_jh; bh = jh2bh(jh); - if (!jbd_trylock_bh_state(bh)) { - jbd_sync_bh(journal, bh); - spin_lock(&journal->j_list_lock); - goto restart; - } if (buffer_locked(bh)) { atomic_inc(&bh->b_count); spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); wait_on_buffer(bh); /* the journal_head may have gone by now */ BUFFER_TRACE(bh, "brelse"); __brelse(bh); - spin_lock(&journal->j_list_lock); - goto restart; + goto out_return_1; } + /* - * Now in whatever state the buffer currently is, we know that - * it has been written out and so we can drop it from the list + * This is foul */ - released = __journal_remove_checkpoint(jh); - jbd_unlock_bh_state(bh); - } + if (!jbd_trylock_bh_state(bh)) { + jbd_sync_bh(journal, bh); + goto out_return_1; + } + + if (jh->b_transaction != NULL) { + transaction_t *t = jh->b_transaction; + tid_t tid = t->t_tid; + + spin_unlock(&journal->j_list_lock); + jbd_unlock_bh_state(bh); + log_start_commit(journal, tid); + log_wait_commit(journal, tid); + goto out_return_1; + } + + /* + * AKPM: I think the buffer_jbddirty test is redundant - it + * shouldn't have NULL b_transaction? + */ + next_jh = jh->b_cpnext; + if (!buffer_dirty(bh) && !buffer_jbddirty(bh)) { + BUFFER_TRACE(bh, "remove from checkpoint"); + __journal_remove_checkpoint(jh); + jbd_unlock_bh_state(bh); + journal_remove_journal_head(bh); + __brelse(bh); + ret = 1; + } else { + jbd_unlock_bh_state(bh); + } + } while (jh != last_jh); + + return ret; +out_return_1: + spin_lock(&journal->j_list_lock); + return 1; } #define NR_BATCH 64 @@ -218,7 +203,9 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) { int i; + spin_unlock(&journal->j_list_lock); ll_rw_block(SWRITE, *batch_count, bhs); + spin_lock(&journal->j_list_lock); for (i = 0; i < *batch_count; i++) { struct buffer_head *bh = bhs[i]; clear_buffer_jwrite(bh); @@ -234,46 +221,19 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) * Return 1 if something happened which requires us to abort the current * scan of the checkpoint list. * - * Called with j_list_lock held and drops it if 1 is returned + * Called with j_list_lock held. * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it */ -static int __process_buffer(journal_t *journal, struct journal_head *jh, - struct buffer_head **bhs, int *batch_count) +static int __flush_buffer(journal_t *journal, struct journal_head *jh, + struct buffer_head **bhs, int *batch_count, + int *drop_count) { struct buffer_head *bh = jh2bh(jh); int ret = 0; - if (buffer_locked(bh)) { - get_bh(bh); - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - wait_on_buffer(bh); - /* the journal_head may have gone by now */ - BUFFER_TRACE(bh, "brelse"); - put_bh(bh); - ret = 1; - } - else if (jh->b_transaction != NULL) { - transaction_t *t = jh->b_transaction; - tid_t tid = t->t_tid; + if (buffer_dirty(bh) && !buffer_locked(bh) && jh->b_jlist == BJ_None) { + J_ASSERT_JH(jh, jh->b_transaction == NULL); - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - log_start_commit(journal, tid); - log_wait_commit(journal, tid); - ret = 1; - } - else if (!buffer_dirty(bh)) { - J_ASSERT_JH(jh, !buffer_jbddirty(bh)); - BUFFER_TRACE(bh, "remove from checkpoint"); - __journal_remove_checkpoint(jh); - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - journal_remove_journal_head(bh); - put_bh(bh); - ret = 1; - } - else { /* * Important: we are about to write the buffer, and * possibly block, while still holding the journal lock. @@ -286,30 +246,45 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, J_ASSERT_BH(bh, !buffer_jwrite(bh)); set_buffer_jwrite(bh); bhs[*batch_count] = bh; - __buffer_relink_io(jh); jbd_unlock_bh_state(bh); (*batch_count)++; if (*batch_count == NR_BATCH) { - spin_unlock(&journal->j_list_lock); __flush_batch(journal, bhs, batch_count); ret = 1; } + } else { + int last_buffer = 0; + if (jh->b_cpnext == jh) { + /* We may be about to drop the transaction. Tell the + * caller that the lists have changed. + */ + last_buffer = 1; + } + if (__try_to_free_cp_buf(jh)) { + (*drop_count)++; + ret = last_buffer; + } } return ret; } /* - * Perform an actual checkpoint. We take the first transaction on the - * list of transactions to be checkpointed and send all its buffers - * to disk. We submit larger chunks of data at once. + * Perform an actual checkpoint. We don't write out only enough to + * satisfy the current blocked requests: rather we submit a reasonably + * sized chunk of the outstanding data to disk at once for + * efficiency. __log_wait_for_space() will retry if we didn't free enough. * + * However, we _do_ take into account the amount requested so that once + * the IO has been queued, we can return as soon as enough of it has + * completed to disk. + * * The journal should be locked before calling this function. */ int log_do_checkpoint(journal_t *journal) { - transaction_t *transaction; - tid_t this_tid; int result; + int batch_count = 0; + struct buffer_head *bhs[NR_BATCH]; jbd_debug(1, "Start checkpoint\n"); @@ -324,70 +299,79 @@ int log_do_checkpoint(journal_t *journal) return result; /* - * OK, we need to start writing disk blocks. Take one transaction - * and write it. + * OK, we need to start writing disk blocks. Try to free up a + * quarter of the log in a single checkpoint if we can. */ - spin_lock(&journal->j_list_lock); - if (!journal->j_checkpoint_transactions) - goto out; - transaction = journal->j_checkpoint_transactions; - this_tid = transaction->t_tid; -restart: /* - * If someone cleaned up this transaction while we slept, we're - * done (maybe it's a new transaction, but it fell at the same - * address). + * AKPM: check this code. I had a feeling a while back that it + * degenerates into a busy loop at unmount time. */ - if (journal->j_checkpoint_transactions == transaction || - transaction->t_tid == this_tid) { - int batch_count = 0; - struct buffer_head *bhs[NR_BATCH]; - struct journal_head *jh; - int retry = 0; - - while (!retry && transaction->t_checkpoint_list) { + spin_lock(&journal->j_list_lock); + while (journal->j_checkpoint_transactions) { + transaction_t *transaction; + struct journal_head *jh, *last_jh, *next_jh; + int drop_count = 0; + int cleanup_ret, retry = 0; + tid_t this_tid; + + transaction = journal->j_checkpoint_transactions; + this_tid = transaction->t_tid; + jh = transaction->t_checkpoint_list; + last_jh = jh->b_cpprev; + next_jh = jh; + do { struct buffer_head *bh; - jh = transaction->t_checkpoint_list; + jh = next_jh; + next_jh = jh->b_cpnext; bh = jh2bh(jh); if (!jbd_trylock_bh_state(bh)) { jbd_sync_bh(journal, bh); + spin_lock(&journal->j_list_lock); retry = 1; break; } - retry = __process_buffer(journal, jh, bhs, - &batch_count); - if (!retry && - lock_need_resched(&journal->j_list_lock)) { - spin_unlock(&journal->j_list_lock); + retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count); + if (cond_resched_lock(&journal->j_list_lock)) { retry = 1; break; } - } + } while (jh != last_jh && !retry); if (batch_count) { - if (!retry) { - spin_unlock(&journal->j_list_lock); - retry = 1; - } __flush_batch(journal, bhs, &batch_count); + retry = 1; } - if (retry) { - spin_lock(&journal->j_list_lock); - goto restart; - } /* - * Now we have cleaned up the first transaction's checkpoint - * list. Let's clean up the second one. + * If someone cleaned up this transaction while we slept, we're + * done + */ + if (journal->j_checkpoint_transactions != transaction) + break; + if (retry) + continue; + /* + * Maybe it's a new transaction, but it fell at the same + * address */ - __wait_cp_io(journal, transaction); + if (transaction->t_tid != this_tid) + continue; + /* + * We have walked the whole transaction list without + * finding anything to write to disk. We had better be + * able to make some progress or we are in trouble. + */ + cleanup_ret = __cleanup_transaction(journal, transaction); + J_ASSERT(drop_count != 0 || cleanup_ret != 0); + if (journal->j_checkpoint_transactions != transaction) + break; } -out: spin_unlock(&journal->j_list_lock); result = cleanup_journal_tail(journal); if (result < 0) return result; + return 0; } @@ -471,53 +455,6 @@ int cleanup_journal_tail(journal_t *journal) /* Checkpoint list management */ -/* - * journal_clean_one_cp_list - * - * Find all the written-back checkpoint buffers in the given list and release them. - * - * Called with the journal locked. - * Called with j_list_lock held. - * Returns number of bufers reaped (for debug) - */ - -static int journal_clean_one_cp_list(struct journal_head *jh, int *released) -{ - struct journal_head *last_jh; - struct journal_head *next_jh = jh; - int ret, freed = 0; - - *released = 0; - if (!jh) - return 0; - - last_jh = jh->b_cpprev; - do { - jh = next_jh; - next_jh = jh->b_cpnext; - /* Use trylock because of the ranking */ - if (jbd_trylock_bh_state(jh2bh(jh))) { - ret = __try_to_free_cp_buf(jh); - if (ret) { - freed++; - if (ret == 2) { - *released = 1; - return freed; - } - } - } - /* - * This function only frees up some memory if possible so we - * dont have an obligation to finish processing. Bail out if - * preemption requested: - */ - if (need_resched()) - return freed; - } while (jh != last_jh); - - return freed; -} - /* * journal_clean_checkpoint_list * @@ -525,38 +462,46 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released) * * Called with the journal locked. * Called with j_list_lock held. - * Returns number of buffers reaped (for debug) + * Returns number of bufers reaped (for debug) */ int __journal_clean_checkpoint_list(journal_t *journal) { transaction_t *transaction, *last_transaction, *next_transaction; - int ret = 0, released; + int ret = 0; transaction = journal->j_checkpoint_transactions; - if (!transaction) + if (transaction == 0) goto out; last_transaction = transaction->t_cpprev; next_transaction = transaction; do { + struct journal_head *jh; + transaction = next_transaction; next_transaction = transaction->t_cpnext; - ret += journal_clean_one_cp_list(transaction-> - t_checkpoint_list, &released); - if (need_resched()) - goto out; - if (released) - continue; - /* - * It is essential that we are as careful as in the case of - * t_checkpoint_list with removing the buffer from the list as - * we can possibly see not yet submitted buffers on io_list - */ - ret += journal_clean_one_cp_list(transaction-> - t_checkpoint_io_list, &released); - if (need_resched()) - goto out; + jh = transaction->t_checkpoint_list; + if (jh) { + struct journal_head *last_jh = jh->b_cpprev; + struct journal_head *next_jh = jh; + + do { + jh = next_jh; + next_jh = jh->b_cpnext; + /* Use trylock because of the ranknig */ + if (jbd_trylock_bh_state(jh2bh(jh))) + ret += __try_to_free_cp_buf(jh); + /* + * This function only frees up some memory + * if possible so we dont have an obligation + * to finish processing. Bail out if preemption + * requested: + */ + if (need_resched()) + goto out; + } while (jh != last_jh); + } } while (transaction != last_transaction); out: return ret; @@ -571,22 +516,18 @@ int __journal_clean_checkpoint_list(journal_t *journal) * buffer updates committed in that transaction have safely been stored * elsewhere on disk. To achieve this, all of the buffers in a * transaction need to be maintained on the transaction's checkpoint - * lists until they have been rewritten, at which point this function is + * list until they have been rewritten, at which point this function is * called to remove the buffer from the existing transaction's - * checkpoint lists. - * - * The function returns 1 if it frees the transaction, 0 otherwise. + * checkpoint list. * * This function is called with the journal locked. * This function is called with j_list_lock held. - * This function is called with jbd_lock_bh_state(jh2bh(jh)) */ -int __journal_remove_checkpoint(struct journal_head *jh) +void __journal_remove_checkpoint(struct journal_head *jh) { transaction_t *transaction; journal_t *journal; - int ret = 0; JBUFFER_TRACE(jh, "entry"); @@ -597,10 +538,8 @@ int __journal_remove_checkpoint(struct journal_head *jh) journal = transaction->t_journal; __buffer_unlink(jh); - jh->b_cp_transaction = NULL; - if (transaction->t_checkpoint_list != NULL || - transaction->t_checkpoint_io_list != NULL) + if (transaction->t_checkpoint_list != NULL) goto out; JBUFFER_TRACE(jh, "transaction has no more buffers"); @@ -626,10 +565,8 @@ int __journal_remove_checkpoint(struct journal_head *jh) /* Just in case anybody was waiting for more transactions to be checkpointed... */ wake_up(&journal->j_wait_logspace); - ret = 1; out: JBUFFER_TRACE(jh, "exit"); - return ret; } /* @@ -691,7 +628,6 @@ void __journal_drop_transaction(journal_t *journal, transaction_t *transaction) J_ASSERT(transaction->t_shadow_list == NULL); J_ASSERT(transaction->t_log_list == NULL); J_ASSERT(transaction->t_checkpoint_list == NULL); - J_ASSERT(transaction->t_checkpoint_io_list == NULL); J_ASSERT(transaction->t_updates == 0); J_ASSERT(journal->j_committing_transaction != transaction); J_ASSERT(journal->j_running_transaction != transaction); diff --git a/trunk/fs/lockd/clntproc.c b/trunk/fs/lockd/clntproc.c index 145524039577..c5a33648e9fd 100644 --- a/trunk/fs/lockd/clntproc.c +++ b/trunk/fs/lockd/clntproc.c @@ -26,12 +26,11 @@ static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); +static void nlmclnt_unlock_callback(struct rpc_task *); +static void nlmclnt_cancel_callback(struct rpc_task *); static int nlm_stat_to_errno(u32 stat); static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); -static const struct rpc_call_ops nlmclnt_unlock_ops; -static const struct rpc_call_ops nlmclnt_cancel_ops; - /* * Cookie counter for NLM requests */ @@ -222,7 +221,8 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) goto done; } clnt->cl_softrtry = nfssrv->client->cl_softrtry; - clnt->cl_intr = nfssrv->client->cl_intr; + clnt->cl_intr = nfssrv->client->cl_intr; + clnt->cl_chatty = nfssrv->client->cl_chatty; } /* Keep the old signal mask */ @@ -399,7 +399,8 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc) /* * Generic NLM call, async version. */ -int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) +int +nlmsvc_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback) { struct nlm_host *host = req->a_host; struct rpc_clnt *clnt; @@ -418,12 +419,13 @@ int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops msg.rpc_proc = &clnt->cl_procinfo[proc]; /* bootstrap and kick off the async RPC call */ - status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req); + status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req); return status; } -static int nlmclnt_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) +static int +nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback) { struct nlm_host *host = req->a_host; struct rpc_clnt *clnt; @@ -446,7 +448,7 @@ static int nlmclnt_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_c /* Increment host refcount */ nlm_get_host(host); /* bootstrap and kick off the async RPC call */ - status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req); + status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req); if (status < 0) nlm_release_host(host); return status; @@ -662,7 +664,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) if (req->a_flags & RPC_TASK_ASYNC) { status = nlmclnt_async_call(req, NLMPROC_UNLOCK, - &nlmclnt_unlock_ops); + nlmclnt_unlock_callback); /* Hrmf... Do the unlock early since locks_remove_posix() * really expects us to free the lock synchronously */ do_vfs_lock(fl); @@ -690,9 +692,10 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) return -ENOLCK; } -static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) +static void +nlmclnt_unlock_callback(struct rpc_task *task) { - struct nlm_rqst *req = data; + struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata; int status = req->a_res.status; if (RPC_ASSASSINATED(task)) @@ -719,10 +722,6 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) rpc_restart_call(task); } -static const struct rpc_call_ops nlmclnt_unlock_ops = { - .rpc_call_done = nlmclnt_unlock_callback, -}; - /* * Cancel a blocked lock request. * We always use an async RPC call for this in order not to hang a @@ -751,7 +750,8 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) nlmclnt_setlockargs(req, fl); - status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); + status = nlmclnt_async_call(req, NLMPROC_CANCEL, + nlmclnt_cancel_callback); if (status < 0) { nlmclnt_release_lockargs(req); kfree(req); @@ -765,9 +765,10 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) return status; } -static void nlmclnt_cancel_callback(struct rpc_task *task, void *data) +static void +nlmclnt_cancel_callback(struct rpc_task *task) { - struct nlm_rqst *req = data; + struct nlm_rqst *req = (struct nlm_rqst *) task->tk_calldata; if (RPC_ASSASSINATED(task)) goto die; @@ -806,10 +807,6 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data) rpc_delay(task, 30 * HZ); } -static const struct rpc_call_ops nlmclnt_cancel_ops = { - .rpc_call_done = nlmclnt_cancel_callback, -}; - /* * Convert an NLM status code to a generic kernel errno */ diff --git a/trunk/fs/lockd/host.c b/trunk/fs/lockd/host.c index 82f7a0b1d8ae..c4c8601096e0 100644 --- a/trunk/fs/lockd/host.c +++ b/trunk/fs/lockd/host.c @@ -177,7 +177,7 @@ nlm_bind_host(struct nlm_host *host) if ((clnt = host->h_rpcclnt) != NULL) { xprt = clnt->cl_xprt; if (time_after_eq(jiffies, host->h_nextrebind)) { - rpc_force_rebind(clnt); + clnt->cl_port = 0; host->h_nextrebind = jiffies + NLM_HOST_REBIND; dprintk("lockd: next rebind in %ld jiffies\n", host->h_nextrebind - jiffies); @@ -217,7 +217,7 @@ nlm_rebind_host(struct nlm_host *host) { dprintk("lockd: rebind host %s\n", host->h_name); if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) { - rpc_force_rebind(host->h_rpcclnt); + host->h_rpcclnt->cl_port = 0; host->h_nextrebind = jiffies + NLM_HOST_REBIND; } } diff --git a/trunk/fs/lockd/mon.c b/trunk/fs/lockd/mon.c index 0edc03e67966..2d144abe84ad 100644 --- a/trunk/fs/lockd/mon.c +++ b/trunk/fs/lockd/mon.c @@ -123,6 +123,7 @@ nsm_create(void) if (IS_ERR(clnt)) goto out_err; clnt->cl_softrtry = 1; + clnt->cl_chatty = 1; clnt->cl_oneshot = 1; return clnt; diff --git a/trunk/fs/lockd/svc.c b/trunk/fs/lockd/svc.c index 71a30b416d1a..12a857c29e25 100644 --- a/trunk/fs/lockd/svc.c +++ b/trunk/fs/lockd/svc.c @@ -178,8 +178,6 @@ lockd(struct svc_rqst *rqstp) } - flush_signals(current); - /* * Check whether there's a new lockd process before * shutting down the hosts and clearing the slot. @@ -194,6 +192,8 @@ lockd(struct svc_rqst *rqstp) "lockd: new process, skipping host shutdown\n"); wake_up(&lockd_exit); + flush_signals(current); + /* Exit the RPC thread */ svc_exit_thread(rqstp); diff --git a/trunk/fs/lockd/svc4proc.c b/trunk/fs/lockd/svc4proc.c index 4063095d849e..489670e21769 100644 --- a/trunk/fs/lockd/svc4proc.c +++ b/trunk/fs/lockd/svc4proc.c @@ -22,8 +22,7 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *); - -static const struct rpc_call_ops nlm4svc_callback_ops; +static void nlm4svc_callback_exit(struct rpc_task *); /* * Obtain client and file from arguments @@ -471,6 +470,7 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, } + /* * This is the generic lockd callback for async RPC calls */ @@ -494,7 +494,7 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) call->a_host = host; memcpy(&call->a_args, resp, sizeof(*resp)); - if (nlmsvc_async_call(call, proc, &nlm4svc_callback_ops) < 0) + if (nlmsvc_async_call(call, proc, nlm4svc_callback_exit) < 0) goto error; return rpc_success; @@ -504,9 +504,10 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) return rpc_system_err; } -static void nlm4svc_callback_exit(struct rpc_task *task, void *data) +static void +nlm4svc_callback_exit(struct rpc_task *task) { - struct nlm_rqst *call = data; + struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata; if (task->tk_status < 0) { dprintk("lockd: %4d callback failed (errno = %d)\n", @@ -516,10 +517,6 @@ static void nlm4svc_callback_exit(struct rpc_task *task, void *data) kfree(call); } -static const struct rpc_call_ops nlm4svc_callback_ops = { - .rpc_call_done = nlm4svc_callback_exit, -}; - /* * NLM Server procedures. */ diff --git a/trunk/fs/lockd/svclock.c b/trunk/fs/lockd/svclock.c index 9cfced65d4a2..49f959796b66 100644 --- a/trunk/fs/lockd/svclock.c +++ b/trunk/fs/lockd/svclock.c @@ -41,8 +41,7 @@ static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); static int nlmsvc_remove_block(struct nlm_block *block); - -static const struct rpc_call_ops nlmsvc_grant_ops; +static void nlmsvc_grant_callback(struct rpc_task *task); /* * The list of blocked locks to retry @@ -227,27 +226,31 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, * It is the caller's responsibility to check whether the file * can be closed hereafter. */ -static int +static void nlmsvc_delete_block(struct nlm_block *block, int unlock) { struct file_lock *fl = &block->b_call.a_args.lock.fl; struct nlm_file *file = block->b_file; struct nlm_block **bp; - int status = 0; dprintk("lockd: deleting block %p...\n", block); /* Remove block from list */ nlmsvc_remove_block(block); - if (unlock) - status = posix_unblock_lock(file->f_file, fl); + if (fl->fl_next) + posix_unblock_lock(file->f_file, fl); + if (unlock) { + fl->fl_type = F_UNLCK; + posix_lock_file(file->f_file, fl); + block->b_granted = 0; + } /* If the block is in the middle of a GRANT callback, * don't kill it yet. */ if (block->b_incall) { nlmsvc_insert_block(block, NLM_NEVER); block->b_done = 1; - return status; + return; } /* Remove block from file's list of blocks */ @@ -262,7 +265,6 @@ nlmsvc_delete_block(struct nlm_block *block, int unlock) nlm_release_host(block->b_host); nlmclnt_freegrantargs(&block->b_call); kfree(block); - return status; } /* @@ -273,7 +275,6 @@ int nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) { struct nlm_block *block, *next; - /* XXX: Will everything get cleaned up if we don't unlock here? */ down(&file->f_sema); for (block = file->f_blocks; block; block = next) { @@ -443,7 +444,6 @@ u32 nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) { struct nlm_block *block; - int status = 0; dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n", file->f_file->f_dentry->d_inode->i_sb->s_id, @@ -454,9 +454,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) down(&file->f_sema); if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) - status = nlmsvc_delete_block(block, 1); + nlmsvc_delete_block(block, 1); up(&file->f_sema); - return status ? nlm_lck_denied : nlm_granted; + return nlm_granted; } /* @@ -562,7 +562,7 @@ nlmsvc_grant_blocked(struct nlm_block *block) /* Call the client */ nlm_get_host(block->b_call.a_host); if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG, - &nlmsvc_grant_ops) < 0) + nlmsvc_grant_callback) < 0) nlm_release_host(block->b_call.a_host); up(&file->f_sema); } @@ -575,9 +575,10 @@ nlmsvc_grant_blocked(struct nlm_block *block) * chain once more in order to have it removed by lockd itself (which can * then sleep on the file semaphore without disrupting e.g. the nfs client). */ -static void nlmsvc_grant_callback(struct rpc_task *task, void *data) +static void +nlmsvc_grant_callback(struct rpc_task *task) { - struct nlm_rqst *call = data; + struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata; struct nlm_block *block; unsigned long timeout; struct sockaddr_in *peer_addr = RPC_PEERADDR(task->tk_client); @@ -613,10 +614,6 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) nlm_release_host(call->a_host); } -static const struct rpc_call_ops nlmsvc_grant_ops = { - .rpc_call_done = nlmsvc_grant_callback, -}; - /* * We received a GRANT_RES callback. Try to find the corresponding * block. @@ -636,12 +633,11 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status file->f_count++; down(&file->f_sema); - block = nlmsvc_find_block(cookie, &rqstp->rq_addr); - if (block) { + if ((block = nlmsvc_find_block(cookie,&rqstp->rq_addr)) != NULL) { if (status == NLM_LCK_DENIED_GRACE_PERIOD) { /* Try again in a couple of seconds */ nlmsvc_insert_block(block, 10 * HZ); - up(&file->f_sema); + block = NULL; } else { /* Lock is now held by client, or has been rejected. * In both cases, the block should be removed. */ @@ -652,6 +648,8 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status nlmsvc_delete_block(block, 1); } } + if (!block) + up(&file->f_sema); nlm_release_file(file); } diff --git a/trunk/fs/lockd/svcproc.c b/trunk/fs/lockd/svcproc.c index 3bc437e0cf5b..757e344cf200 100644 --- a/trunk/fs/lockd/svcproc.c +++ b/trunk/fs/lockd/svcproc.c @@ -23,8 +23,7 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT static u32 nlmsvc_callback(struct svc_rqst *, u32, struct nlm_res *); - -static const struct rpc_call_ops nlmsvc_callback_ops; +static void nlmsvc_callback_exit(struct rpc_task *); #ifdef CONFIG_LOCKD_V4 static u32 @@ -519,7 +518,7 @@ nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) call->a_host = host; memcpy(&call->a_args, resp, sizeof(*resp)); - if (nlmsvc_async_call(call, proc, &nlmsvc_callback_ops) < 0) + if (nlmsvc_async_call(call, proc, nlmsvc_callback_exit) < 0) goto error; return rpc_success; @@ -529,9 +528,10 @@ nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) return rpc_system_err; } -static void nlmsvc_callback_exit(struct rpc_task *task, void *data) +static void +nlmsvc_callback_exit(struct rpc_task *task) { - struct nlm_rqst *call = data; + struct nlm_rqst *call = (struct nlm_rqst *) task->tk_calldata; if (task->tk_status < 0) { dprintk("lockd: %4d callback failed (errno = %d)\n", @@ -541,10 +541,6 @@ static void nlmsvc_callback_exit(struct rpc_task *task, void *data) kfree(call); } -static const struct rpc_call_ops nlmsvc_callback_ops = { - .rpc_call_done = nlmsvc_callback_exit, -}; - /* * NLM Server procedures. */ diff --git a/trunk/fs/lockd/xdr4.c b/trunk/fs/lockd/xdr4.c index fdcf105a5303..ae4d6b426c62 100644 --- a/trunk/fs/lockd/xdr4.c +++ b/trunk/fs/lockd/xdr4.c @@ -354,9 +354,7 @@ nlm4svc_decode_reboot(struct svc_rqst *rqstp, u32 *p, struct nlm_reboot *argp) return 0; argp->state = ntohl(*p++); /* Preserve the address in network byte order */ - argp->addr = *p++; - argp->vers = *p++; - argp->proto = *p++; + argp->addr = *p++; return xdr_argsize_check(rqstp, p); } diff --git a/trunk/fs/locks.c b/trunk/fs/locks.c index fb32d6218e21..250ef53d25ef 100644 --- a/trunk/fs/locks.c +++ b/trunk/fs/locks.c @@ -1958,18 +1958,22 @@ EXPORT_SYMBOL(posix_block_lock); * * lockd needs to block waiting for locks. */ -int +void posix_unblock_lock(struct file *filp, struct file_lock *waiter) { - int status = 0; - + /* + * A remote machine may cancel the lock request after it's been + * granted locally. If that happens, we need to delete the lock. + */ lock_kernel(); - if (waiter->fl_next) + if (waiter->fl_next) { __locks_delete_block(waiter); - else - status = -ENOENT; - unlock_kernel(); - return status; + unlock_kernel(); + } else { + unlock_kernel(); + waiter->fl_type = F_UNLCK; + posix_lock_file(filp, waiter); + } } EXPORT_SYMBOL(posix_unblock_lock); diff --git a/trunk/fs/nfs/Makefile b/trunk/fs/nfs/Makefile index ec61fd56a1a9..8b3bb715d177 100644 --- a/trunk/fs/nfs/Makefile +++ b/trunk/fs/nfs/Makefile @@ -13,5 +13,4 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \ delegation.o idmap.o \ callback.o callback_xdr.o callback_proc.o nfs-$(CONFIG_NFS_DIRECTIO) += direct.o -nfs-$(CONFIG_SYSCTL) += sysctl.o nfs-objs := $(nfs-y) diff --git a/trunk/fs/nfs/callback.c b/trunk/fs/nfs/callback.c index fcd97406a778..30cae3602867 100644 --- a/trunk/fs/nfs/callback.c +++ b/trunk/fs/nfs/callback.c @@ -34,7 +34,6 @@ static struct nfs_callback_data nfs_callback_info; static DECLARE_MUTEX(nfs_callback_sema); static struct svc_program nfs4_callback_program; -unsigned int nfs_callback_set_tcpport; unsigned short nfs_callback_tcpport; /* @@ -99,7 +98,7 @@ int nfs_callback_up(void) if (!serv) goto out_err; /* FIXME: We don't want to register this socket with the portmapper */ - ret = svc_makesock(serv, IPPROTO_TCP, nfs_callback_set_tcpport); + ret = svc_makesock(serv, IPPROTO_TCP, 0); if (ret < 0) goto out_destroy; if (!list_empty(&serv->sv_permsocks)) { diff --git a/trunk/fs/nfs/callback.h b/trunk/fs/nfs/callback.h index b252e7fe53a5..a0db2d4f9415 100644 --- a/trunk/fs/nfs/callback.h +++ b/trunk/fs/nfs/callback.h @@ -65,7 +65,6 @@ extern unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy); extern int nfs_callback_up(void); extern int nfs_callback_down(void); -extern unsigned int nfs_callback_set_tcpport; extern unsigned short nfs_callback_tcpport; #endif /* __LINUX_FS_NFS_CALLBACK_H */ diff --git a/trunk/fs/nfs/callback_proc.c b/trunk/fs/nfs/callback_proc.c index 462cfceb50c5..65f1e19e4d19 100644 --- a/trunk/fs/nfs/callback_proc.c +++ b/trunk/fs/nfs/callback_proc.c @@ -35,9 +35,7 @@ unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0) goto out_iput; res->size = i_size_read(inode); - res->change_attr = delegation->change_attr; - if (nfsi->npages != 0) - res->change_attr++; + res->change_attr = NFS_CHANGE_ATTR(inode); res->ctime = inode->i_ctime; res->mtime = inode->i_mtime; res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) & diff --git a/trunk/fs/nfs/delegation.c b/trunk/fs/nfs/delegation.c index c6f07c1c71e6..618a327027b3 100644 --- a/trunk/fs/nfs/delegation.c +++ b/trunk/fs/nfs/delegation.c @@ -8,7 +8,6 @@ */ #include #include -#include #include #include #include @@ -131,7 +130,6 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct sizeof(delegation->stateid.data)); delegation->type = res->delegation_type; delegation->maxsize = res->maxsize; - delegation->change_attr = nfsi->change_attr; delegation->cred = get_rpccred(cred); delegation->inode = inode; @@ -159,6 +157,8 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation * { int res = 0; + __nfs_revalidate_inode(NFS_SERVER(inode), inode); + res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid); nfs_free_delegation(delegation); return res; @@ -231,49 +231,6 @@ void nfs_return_all_delegations(struct super_block *sb) spin_unlock(&clp->cl_lock); } -int nfs_do_expire_all_delegations(void *ptr) -{ - struct nfs4_client *clp = ptr; - struct nfs_delegation *delegation; - struct inode *inode; - - allow_signal(SIGKILL); -restart: - spin_lock(&clp->cl_lock); - if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0) - goto out; - if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) - goto out; - list_for_each_entry(delegation, &clp->cl_delegations, super_list) { - inode = igrab(delegation->inode); - if (inode == NULL) - continue; - spin_unlock(&clp->cl_lock); - nfs_inode_return_delegation(inode); - iput(inode); - goto restart; - } -out: - spin_unlock(&clp->cl_lock); - nfs4_put_client(clp); - module_put_and_exit(0); -} - -void nfs_expire_all_delegations(struct nfs4_client *clp) -{ - struct task_struct *task; - - __module_get(THIS_MODULE); - atomic_inc(&clp->cl_count); - task = kthread_run(nfs_do_expire_all_delegations, clp, - "%u.%u.%u.%u-delegreturn", - NIPQUAD(clp->cl_addr)); - if (!IS_ERR(task)) - return; - nfs4_put_client(clp); - module_put(THIS_MODULE); -} - /* * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. */ diff --git a/trunk/fs/nfs/delegation.h b/trunk/fs/nfs/delegation.h index 7a0b2bfce771..2fcc30de924b 100644 --- a/trunk/fs/nfs/delegation.h +++ b/trunk/fs/nfs/delegation.h @@ -21,7 +21,6 @@ struct nfs_delegation { #define NFS_DELEGATION_NEED_RECLAIM 1 long flags; loff_t maxsize; - __u64 change_attr; }; int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); @@ -31,7 +30,6 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle); void nfs_return_all_delegations(struct super_block *sb); -void nfs_expire_all_delegations(struct nfs4_client *clp); void nfs_handle_cb_pathdown(struct nfs4_client *clp); void nfs_delegation_mark_reclaim(struct nfs4_client *clp); diff --git a/trunk/fs/nfs/dir.c b/trunk/fs/nfs/dir.c index e9255198f767..c0d1a214572c 100644 --- a/trunk/fs/nfs/dir.c +++ b/trunk/fs/nfs/dir.c @@ -1550,10 +1550,8 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, } nfs_inode_return_delegation(old_inode); - if (new_inode != NULL) { - nfs_inode_return_delegation(new_inode); + if (new_inode) d_delete(new_dentry); - } nfs_begin_data_update(old_dir); nfs_begin_data_update(new_dir); diff --git a/trunk/fs/nfs/direct.c b/trunk/fs/nfs/direct.c index 10ae377e68ff..079228817603 100644 --- a/trunk/fs/nfs/direct.c +++ b/trunk/fs/nfs/direct.c @@ -122,10 +122,9 @@ nfs_free_user_pages(struct page **pages, int npages, int do_dirty) { int i; for (i = 0; i < npages; i++) { - struct page *page = pages[i]; - if (do_dirty && !PageCompound(page)) - set_page_dirty_lock(page); - page_cache_release(page); + if (do_dirty) + set_page_dirty_lock(pages[i]); + page_cache_release(pages[i]); } kfree(pages); } @@ -155,7 +154,6 @@ static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, unsigned int struct list_head *list; struct nfs_direct_req *dreq; unsigned int reads = 0; - unsigned int rpages = (rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; dreq = kmem_cache_alloc(nfs_direct_cachep, SLAB_KERNEL); if (!dreq) @@ -169,7 +167,7 @@ static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, unsigned int list = &dreq->list; for(;;) { - struct nfs_read_data *data = nfs_readdata_alloc(rpages); + struct nfs_read_data *data = nfs_readdata_alloc(); if (unlikely(!data)) { while (!list_empty(list)) { @@ -270,6 +268,8 @@ static void nfs_direct_read_schedule(struct nfs_direct_req *dreq, NFS_PROTO(inode)->read_setup(data); data->task.tk_cookie = (unsigned long) inode; + data->task.tk_calldata = data; + data->task.tk_release = nfs_readdata_release; data->complete = nfs_direct_read_result; lock_kernel(); @@ -433,7 +433,7 @@ static ssize_t nfs_direct_write_seg(struct inode *inode, struct nfs_writeverf first_verf; struct nfs_write_data *wdata; - wdata = nfs_writedata_alloc(NFS_SERVER(inode)->wpages); + wdata = nfs_writedata_alloc(); if (!wdata) return -ENOMEM; @@ -662,10 +662,10 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t .iov_len = count, }; - dprintk("nfs: direct read(%s/%s, %lu@%Ld)\n", + dprintk("nfs: direct read(%s/%s, %lu@%lu)\n", file->f_dentry->d_parent->d_name.name, file->f_dentry->d_name.name, - (unsigned long) count, (long long) pos); + (unsigned long) count, (unsigned long) pos); if (!is_sync_kiocb(iocb)) goto out; @@ -718,7 +718,9 @@ nfs_file_direct_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t pos) { - ssize_t retval; + ssize_t retval = -EINVAL; + loff_t *ppos = &iocb->ki_pos; + unsigned long limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; struct file *file = iocb->ki_filp; struct nfs_open_context *ctx = (struct nfs_open_context *) file->private_data; @@ -726,32 +728,35 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, struct inode *inode = mapping->host; struct iovec iov = { .iov_base = (char __user *)buf, + .iov_len = count, }; - dfprintk(VFS, "nfs: direct write(%s/%s, %lu@%Ld)\n", + dfprintk(VFS, "nfs: direct write(%s/%s(%ld), %lu@%lu)\n", file->f_dentry->d_parent->d_name.name, - file->f_dentry->d_name.name, - (unsigned long) count, (long long) pos); + file->f_dentry->d_name.name, inode->i_ino, + (unsigned long) count, (unsigned long) pos); - retval = -EINVAL; if (!is_sync_kiocb(iocb)) goto out; - - retval = generic_write_checks(file, &pos, &count, 0); - if (retval) + if (count < 0) goto out; - - retval = -EINVAL; - if ((ssize_t) count < 0) + if (pos < 0) goto out; - retval = 0; - if (!count) - goto out; - iov.iov_len = count, - retval = -EFAULT; if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len)) goto out; + retval = -EFBIG; + if (limit != RLIM_INFINITY) { + if (pos >= limit) { + send_sig(SIGXFSZ, current, 0); + goto out; + } + if (count > limit - (unsigned long) pos) + count = limit - (unsigned long) pos; + } + retval = 0; + if (!count) + goto out; retval = nfs_sync_mapping(mapping); if (retval) @@ -761,7 +766,7 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count, if (mapping->nrpages) invalidate_inode_pages2(mapping); if (retval > 0) - iocb->ki_pos = pos + retval; + *ppos = pos + retval; out: return retval; diff --git a/trunk/fs/nfs/idmap.c b/trunk/fs/nfs/idmap.c index 821edd30333b..ffb8df91dc34 100644 --- a/trunk/fs/nfs/idmap.c +++ b/trunk/fs/nfs/idmap.c @@ -54,11 +54,7 @@ #define IDMAP_HASH_SZ 128 -/* Default cache timeout is 10 minutes */ -unsigned int nfs_idmap_cache_timeout = 600 * HZ; - struct idmap_hashent { - unsigned long ih_expires; __u32 ih_id; int ih_namelen; char ih_name[IDMAP_NAMESZ]; @@ -153,8 +149,6 @@ idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len) if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0) return NULL; - if (time_after(jiffies, he->ih_expires)) - return NULL; return he; } @@ -170,8 +164,6 @@ idmap_lookup_id(struct idmap_hashtable *h, __u32 id) struct idmap_hashent *he = idmap_id_hash(h, id); if (he->ih_id != id || he->ih_namelen == 0) return NULL; - if (time_after(jiffies, he->ih_expires)) - return NULL; return he; } @@ -200,7 +192,6 @@ idmap_update_entry(struct idmap_hashent *he, const char *name, memcpy(he->ih_name, name, namelen); he->ih_name[namelen] = '\0'; he->ih_namelen = namelen; - he->ih_expires = jiffies + nfs_idmap_cache_timeout; } /* diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index e7bd0d92600f..432f41cd75e6 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -40,7 +40,6 @@ #include #include "nfs4_fs.h" -#include "callback.h" #include "delegation.h" #define NFSDBG_FACILITY NFSDBG_VFS @@ -222,10 +221,10 @@ nfs_calc_block_size(u64 tsize) static inline unsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp) { - if (bsize < NFS_MIN_FILE_IO_SIZE) - bsize = NFS_DEF_FILE_IO_SIZE; - else if (bsize >= NFS_MAX_FILE_IO_SIZE) - bsize = NFS_MAX_FILE_IO_SIZE; + if (bsize < 1024) + bsize = NFS_DEF_FILE_IO_BUFFER_SIZE; + else if (bsize >= NFS_MAX_FILE_IO_BUFFER_SIZE) + bsize = NFS_MAX_FILE_IO_BUFFER_SIZE; return nfs_block_bits(bsize, nrbitsp); } @@ -308,15 +307,20 @@ nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor) max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); if (server->rsize > max_rpc_payload) server->rsize = max_rpc_payload; - if (server->rsize > NFS_MAX_FILE_IO_SIZE) - server->rsize = NFS_MAX_FILE_IO_SIZE; - server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - if (server->wsize > max_rpc_payload) server->wsize = max_rpc_payload; - if (server->wsize > NFS_MAX_FILE_IO_SIZE) - server->wsize = NFS_MAX_FILE_IO_SIZE; + + server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + if (server->rpages > NFS_READ_MAXIOV) { + server->rpages = NFS_READ_MAXIOV; + server->rsize = server->rpages << PAGE_CACHE_SHIFT; + } + server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + if (server->wpages > NFS_WRITE_MAXIOV) { + server->wpages = NFS_WRITE_MAXIOV; + server->wsize = server->wpages << PAGE_CACHE_SHIFT; + } if (sb->s_blocksize == 0) sb->s_blocksize = nfs_block_bits(server->wsize, @@ -413,6 +417,7 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) clnt->cl_intr = 1; clnt->cl_softrtry = 1; + clnt->cl_chatty = 1; return clnt; @@ -570,10 +575,11 @@ nfs_statfs(struct super_block *sb, struct kstatfs *buf) buf->f_namelen = server->namelen; out: unlock_kernel(); + return 0; out_err: - dprintk("%s: statfs error = %d\n", __FUNCTION__, -error); + printk(KERN_WARNING "nfs_statfs: statfs error = %d\n", -error); buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; goto out; @@ -952,8 +958,6 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; int err; - /* Flush out writes to the server in order to update c/mtime */ - nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT); if (__IS_FLG(inode, MS_NOATIME)) need_atime = 0; else if (__IS_FLG(inode, MS_NODIRATIME) && S_ISDIR(inode->i_mode)) @@ -1248,33 +1252,6 @@ void nfs_end_data_update(struct inode *inode) atomic_dec(&nfsi->data_updates); } -static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) -{ - struct nfs_inode *nfsi = NFS_I(inode); - - if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0 - && nfsi->change_attr == fattr->pre_change_attr) { - nfsi->change_attr = fattr->change_attr; - nfsi->cache_change_attribute = jiffies; - } - - /* If we have atomic WCC data, we may update some attributes */ - if ((fattr->valid & NFS_ATTR_WCC) != 0) { - if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { - memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); - nfsi->cache_change_attribute = jiffies; - } - if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { - memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); - nfsi->cache_change_attribute = jiffies; - } - if (inode->i_size == fattr->pre_size && nfsi->npages == 0) { - inode->i_size = fattr->size; - nfsi->cache_change_attribute = jiffies; - } - } -} - /** * nfs_check_inode_attributes - verify consistency of the inode attribute cache * @inode - pointer to inode @@ -1291,20 +1268,22 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat int data_unstable; - if ((fattr->valid & NFS_ATTR_FATTR) == 0) - return 0; - /* Are we in the process of updating data on the server? */ data_unstable = nfs_caches_unstable(inode); - /* Do atomic weak cache consistency updates */ - nfs_wcc_update_inode(inode, fattr); + if (fattr->valid & NFS_ATTR_FATTR_V4) { + if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0 + && nfsi->change_attr == fattr->pre_change_attr) + nfsi->change_attr = fattr->change_attr; + if (nfsi->change_attr != fattr->change_attr) { + nfsi->cache_validity |= NFS_INO_INVALID_ATTR; + if (!data_unstable) + nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; + } + } - if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && - nfsi->change_attr != fattr->change_attr) { - nfsi->cache_validity |= NFS_INO_INVALID_ATTR; - if (!data_unstable) - nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; + if ((fattr->valid & NFS_ATTR_FATTR) == 0) { + return 0; } /* Has the inode gone and changed behind our back? */ @@ -1316,6 +1295,14 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat cur_size = i_size_read(inode); new_isize = nfs_size_to_loff_t(fattr->size); + /* If we have atomic WCC data, we may update some attributes */ + if ((fattr->valid & NFS_ATTR_WCC) != 0) { + if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) + memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); + if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) + memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); + } + /* Verify a few of the more important attributes */ if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { nfsi->cache_validity |= NFS_INO_INVALID_ATTR; @@ -1423,8 +1410,14 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) if ((fattr->valid & NFS_ATTR_FATTR) == 0) return 0; - if (nfsi->fileid != fattr->fileid) - goto out_fileid; + if (nfsi->fileid != fattr->fileid) { + printk(KERN_ERR "%s: inode number mismatch\n" + "expected (%s/0x%Lx), got (%s/0x%Lx)\n", + __FUNCTION__, + inode->i_sb->s_id, (long long)nfsi->fileid, + inode->i_sb->s_id, (long long)fattr->fileid); + goto out_err; + } /* * Make sure the inode's type hasn't changed. @@ -1443,9 +1436,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) if (data_stable) nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); - /* Do atomic weak cache consistency updates */ - nfs_wcc_update_inode(inode, fattr); - /* Check if our cached file size is stale */ new_isize = nfs_size_to_loff_t(fattr->size); cur_isize = i_size_read(inode); @@ -1549,13 +1539,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) */ nfs_invalidate_inode(inode); return -ESTALE; - - out_fileid: - printk(KERN_ERR "NFS: server %s error: fileid changed\n" - "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", - NFS_SERVER(inode)->hostname, inode->i_sb->s_id, - (long long)nfsi->fileid, (long long)fattr->fileid); - goto out_err; } /* @@ -1837,10 +1820,25 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, } clnt->cl_intr = 1; clnt->cl_softrtry = 1; + clnt->cl_chatty = 1; clp->cl_rpcclient = clnt; + clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, 0); + if (IS_ERR(clp->cl_cred)) { + up_write(&clp->cl_sem); + err = PTR_ERR(clp->cl_cred); + clp->cl_cred = NULL; + goto out_fail; + } memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr)); nfs_idmap_new(clp); } + if (list_empty(&clp->cl_superblocks)) { + err = nfs4_init_client(clp); + if (err != 0) { + up_write(&clp->cl_sem); + goto out_fail; + } + } list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); clnt = rpc_clone_client(clp->cl_rpcclient); if (!IS_ERR(clnt)) @@ -2035,35 +2033,6 @@ static struct file_system_type nfs4_fs_type = { .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; -static const int nfs_set_port_min = 0; -static const int nfs_set_port_max = 65535; -static int param_set_port(const char *val, struct kernel_param *kp) -{ - char *endp; - int num = simple_strtol(val, &endp, 0); - if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max) - return -EINVAL; - *((int *)kp->arg) = num; - return 0; -} - -module_param_call(callback_tcpport, param_set_port, param_get_int, - &nfs_callback_set_tcpport, 0644); - -static int param_set_idmap_timeout(const char *val, struct kernel_param *kp) -{ - char *endp; - int num = simple_strtol(val, &endp, 0); - int jif = num * HZ; - if (endp == val || *endp || num < 0 || jif < num) - return -EINVAL; - *((int *)kp->arg) = jif; - return 0; -} - -module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, - &nfs_idmap_cache_timeout, 0644); - #define nfs4_init_once(nfsi) \ do { \ INIT_LIST_HEAD(&(nfsi)->open_states); \ @@ -2071,25 +2040,8 @@ module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, nfsi->delegation_state = 0; \ init_rwsem(&nfsi->rwsem); \ } while(0) - -static inline int register_nfs4fs(void) -{ - int ret; - - ret = nfs_register_sysctl(); - if (ret != 0) - return ret; - ret = register_filesystem(&nfs4_fs_type); - if (ret != 0) - nfs_unregister_sysctl(); - return ret; -} - -static inline void unregister_nfs4fs(void) -{ - unregister_filesystem(&nfs4_fs_type); - nfs_unregister_sysctl(); -} +#define register_nfs4fs() register_filesystem(&nfs4_fs_type) +#define unregister_nfs4fs() unregister_filesystem(&nfs4_fs_type) #else #define nfs4_init_once(nfsi) \ do { } while (0) @@ -2214,11 +2166,11 @@ static int __init init_nfs_fs(void) #ifdef CONFIG_PROC_FS rpc_proc_unregister("nfs"); #endif + nfs_destroy_writepagecache(); #ifdef CONFIG_NFS_DIRECTIO - nfs_destroy_directcache(); out0: + nfs_destroy_directcache(); #endif - nfs_destroy_writepagecache(); out1: nfs_destroy_readpagecache(); out2: diff --git a/trunk/fs/nfs/mount_clnt.c b/trunk/fs/nfs/mount_clnt.c index db99b8f678f8..0e82617f2de0 100644 --- a/trunk/fs/nfs/mount_clnt.c +++ b/trunk/fs/nfs/mount_clnt.c @@ -82,6 +82,7 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version, RPC_AUTH_UNIX); if (!IS_ERR(clnt)) { clnt->cl_softrtry = 1; + clnt->cl_chatty = 1; clnt->cl_oneshot = 1; clnt->cl_intr = 1; } diff --git a/trunk/fs/nfs/nfs2xdr.c b/trunk/fs/nfs/nfs2xdr.c index 7fc0560c89c9..59049e864ca7 100644 --- a/trunk/fs/nfs/nfs2xdr.c +++ b/trunk/fs/nfs/nfs2xdr.c @@ -146,23 +146,23 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) return p; } +#define SATTR(p, attr, flag, field) \ + *p++ = (attr->ia_valid & flag) ? htonl(attr->field) : ~(u32) 0 static inline u32 * xdr_encode_sattr(u32 *p, struct iattr *attr) { - const u32 not_set = __constant_htonl(0xFFFFFFFF); - - *p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set; - *p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set; - *p++ = (attr->ia_valid & ATTR_GID) ? htonl(attr->ia_gid) : not_set; - *p++ = (attr->ia_valid & ATTR_SIZE) ? htonl(attr->ia_size) : not_set; + SATTR(p, attr, ATTR_MODE, ia_mode); + SATTR(p, attr, ATTR_UID, ia_uid); + SATTR(p, attr, ATTR_GID, ia_gid); + SATTR(p, attr, ATTR_SIZE, ia_size); if (attr->ia_valid & ATTR_ATIME_SET) { p = xdr_encode_time(p, &attr->ia_atime); } else if (attr->ia_valid & ATTR_ATIME) { p = xdr_encode_current_server_time(p, &attr->ia_atime); } else { - *p++ = not_set; - *p++ = not_set; + *p++ = ~(u32) 0; + *p++ = ~(u32) 0; } if (attr->ia_valid & ATTR_MTIME_SET) { @@ -170,11 +170,12 @@ xdr_encode_sattr(u32 *p, struct iattr *attr) } else if (attr->ia_valid & ATTR_MTIME) { p = xdr_encode_current_server_time(p, &attr->ia_mtime); } else { - *p++ = not_set; - *p++ = not_set; + *p++ = ~(u32) 0; + *p++ = ~(u32) 0; } return p; } +#undef SATTR /* * NFS encode functions diff --git a/trunk/fs/nfs/nfs3proc.c b/trunk/fs/nfs/nfs3proc.c index ed67567f0556..92c870d19ccd 100644 --- a/trunk/fs/nfs/nfs3proc.c +++ b/trunk/fs/nfs/nfs3proc.c @@ -68,38 +68,26 @@ nfs3_async_handle_jukebox(struct rpc_task *task) return 1; } +/* + * Bare-bones access to getattr: this is for nfs_read_super. + */ static int -do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle, - struct nfs_fsinfo *info) +nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, + struct nfs_fsinfo *info) { int status; dprintk("%s: call fsinfo\n", __FUNCTION__); nfs_fattr_init(info->fattr); - status = rpc_call(client, NFS3PROC_FSINFO, fhandle, info, 0); + status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status); if (!(info->fattr->valid & NFS_ATTR_FATTR)) { - status = rpc_call(client, NFS3PROC_GETATTR, fhandle, info->fattr, 0); + status = rpc_call(server->client_sys, NFS3PROC_GETATTR, fhandle, info->fattr, 0); dprintk("%s: reply getattr: %d\n", __FUNCTION__, status); } return status; } -/* - * Bare-bones access to getattr: this is for nfs_read_super. - */ -static int -nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info) -{ - int status; - - status = do_proc_get_root(server->client, fhandle, info); - if (status && server->client_sys != server->client) - status = do_proc_get_root(server->client_sys, fhandle, info); - return status; -} - /* * One function for each procedure in the NFS protocol. */ @@ -744,23 +732,19 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); -static void nfs3_read_done(struct rpc_task *task, void *calldata) +static void +nfs3_read_done(struct rpc_task *task) { - struct nfs_read_data *data = calldata; + struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; if (nfs3_async_handle_jukebox(task)) return; /* Call back common NFS readpage processing */ if (task->tk_status >= 0) nfs_refresh_inode(data->inode, &data->fattr); - nfs_readpage_result(task, calldata); + nfs_readpage_result(task); } -static const struct rpc_call_ops nfs3_read_ops = { - .rpc_call_done = nfs3_read_done, - .rpc_release = nfs_readdata_release, -}; - static void nfs3_proc_read_setup(struct nfs_read_data *data) { @@ -778,26 +762,23 @@ nfs3_proc_read_setup(struct nfs_read_data *data) flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_read_ops, data); + rpc_init_task(task, NFS_CLIENT(inode), nfs3_read_done, flags); rpc_call_setup(task, &msg, 0); } -static void nfs3_write_done(struct rpc_task *task, void *calldata) +static void +nfs3_write_done(struct rpc_task *task) { - struct nfs_write_data *data = calldata; + struct nfs_write_data *data; if (nfs3_async_handle_jukebox(task)) return; + data = (struct nfs_write_data *)task->tk_calldata; if (task->tk_status >= 0) nfs_post_op_update_inode(data->inode, data->res.fattr); - nfs_writeback_done(task, calldata); + nfs_writeback_done(task); } -static const struct rpc_call_ops nfs3_write_ops = { - .rpc_call_done = nfs3_write_done, - .rpc_release = nfs_writedata_release, -}; - static void nfs3_proc_write_setup(struct nfs_write_data *data, int how) { @@ -825,26 +806,23 @@ nfs3_proc_write_setup(struct nfs_write_data *data, int how) flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_write_ops, data); + rpc_init_task(task, NFS_CLIENT(inode), nfs3_write_done, flags); rpc_call_setup(task, &msg, 0); } -static void nfs3_commit_done(struct rpc_task *task, void *calldata) +static void +nfs3_commit_done(struct rpc_task *task) { - struct nfs_write_data *data = calldata; + struct nfs_write_data *data; if (nfs3_async_handle_jukebox(task)) return; + data = (struct nfs_write_data *)task->tk_calldata; if (task->tk_status >= 0) nfs_post_op_update_inode(data->inode, data->res.fattr); - nfs_commit_done(task, calldata); + nfs_commit_done(task); } -static const struct rpc_call_ops nfs3_commit_ops = { - .rpc_call_done = nfs3_commit_done, - .rpc_release = nfs_commit_release, -}; - static void nfs3_proc_commit_setup(struct nfs_write_data *data, int how) { @@ -862,7 +840,7 @@ nfs3_proc_commit_setup(struct nfs_write_data *data, int how) flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_commit_ops, data); + rpc_init_task(task, NFS_CLIENT(inode), nfs3_commit_done, flags); rpc_call_setup(task, &msg, 0); } diff --git a/trunk/fs/nfs/nfs3xdr.c b/trunk/fs/nfs/nfs3xdr.c index b6c0b5012bce..0498bd36602c 100644 --- a/trunk/fs/nfs/nfs3xdr.c +++ b/trunk/fs/nfs/nfs3xdr.c @@ -182,7 +182,7 @@ xdr_encode_sattr(u32 *p, struct iattr *attr) { if (attr->ia_valid & ATTR_MODE) { *p++ = xdr_one; - *p++ = htonl(attr->ia_mode & S_IALLUGO); + *p++ = htonl(attr->ia_mode); } else { *p++ = xdr_zero; } diff --git a/trunk/fs/nfs/nfs4_fs.h b/trunk/fs/nfs/nfs4_fs.h index 0f5e4e7cddec..b7f262dcb6e3 100644 --- a/trunk/fs/nfs/nfs4_fs.h +++ b/trunk/fs/nfs/nfs4_fs.h @@ -38,8 +38,7 @@ struct idmap; ((err) != NFSERR_NOFILEHANDLE)) enum nfs4_client_state { - NFS4CLNT_STATE_RECOVER = 0, - NFS4CLNT_LEASE_EXPIRED, + NFS4CLNT_OK = 0, }; /* @@ -68,6 +67,7 @@ struct nfs4_client { atomic_t cl_count; struct rpc_clnt * cl_rpcclient; + struct rpc_cred * cl_cred; struct list_head cl_superblocks; /* List of nfs_server structs */ @@ -76,6 +76,7 @@ struct nfs4_client { struct work_struct cl_renewd; struct work_struct cl_recoverd; + wait_queue_head_t cl_waitq; struct rpc_wait_queue cl_rpcwaitq; /* used for the setclientid verifier */ @@ -181,9 +182,8 @@ struct nfs4_state { nfs4_stateid stateid; - unsigned int n_rdonly; - unsigned int n_wronly; - unsigned int n_rdwr; + unsigned int nreaders; + unsigned int nwriters; int state; /* State on the server (R,W, or RW) */ atomic_t count; }; @@ -210,10 +210,10 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t); /* nfs4proc.c */ extern int nfs4_map_errors(int err); -extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short, struct rpc_cred *); -extern int nfs4_proc_setclientid_confirm(struct nfs4_client *, struct rpc_cred *); -extern int nfs4_proc_async_renew(struct nfs4_client *, struct rpc_cred *); -extern int nfs4_proc_renew(struct nfs4_client *, struct rpc_cred *); +extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short); +extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); +extern int nfs4_proc_async_renew(struct nfs4_client *); +extern int nfs4_proc_renew(struct nfs4_client *); extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state); extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); @@ -237,8 +237,8 @@ extern void init_nfsv4_state(struct nfs_server *); extern void destroy_nfsv4_state(struct nfs_server *); extern struct nfs4_client *nfs4_get_client(struct in_addr *); extern void nfs4_put_client(struct nfs4_client *clp); +extern int nfs4_init_client(struct nfs4_client *clp); extern struct nfs4_client *nfs4_find_client(struct in_addr *); -struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp); extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *); extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); diff --git a/trunk/fs/nfs/nfs4proc.c b/trunk/fs/nfs/nfs4proc.c index 984ca3454d04..f988a9417b13 100644 --- a/trunk/fs/nfs/nfs4proc.c +++ b/trunk/fs/nfs/nfs4proc.c @@ -57,13 +57,11 @@ #define NFS4_POLL_RETRY_MIN (1*HZ) #define NFS4_POLL_RETRY_MAX (15*HZ) -struct nfs4_opendata; -static int _nfs4_proc_open(struct nfs4_opendata *data); +static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid); static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); -static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp); extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); extern struct rpc_procinfo nfs4_procedures[]; @@ -175,7 +173,8 @@ static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry, kunmap_atomic(start, KM_USER0); } -static void renew_lease(const struct nfs_server *server, unsigned long timestamp) +static void +renew_lease(struct nfs_server *server, unsigned long timestamp) { struct nfs4_client *clp = server->nfs4_state; spin_lock(&clp->cl_lock); @@ -195,123 +194,21 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf spin_unlock(&inode->i_lock); } -struct nfs4_opendata { - atomic_t count; - struct nfs_openargs o_arg; - struct nfs_openres o_res; - struct nfs_open_confirmargs c_arg; - struct nfs_open_confirmres c_res; - struct nfs_fattr f_attr; - struct nfs_fattr dir_attr; - struct dentry *dentry; - struct dentry *dir; - struct nfs4_state_owner *owner; - struct iattr attrs; - unsigned long timestamp; - int rpc_status; - int cancelled; -}; - -static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, - struct nfs4_state_owner *sp, int flags, - const struct iattr *attrs) -{ - struct dentry *parent = dget_parent(dentry); - struct inode *dir = parent->d_inode; - struct nfs_server *server = NFS_SERVER(dir); - struct nfs4_opendata *p; - - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (p == NULL) - goto err; - p->o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); - if (p->o_arg.seqid == NULL) - goto err_free; - atomic_set(&p->count, 1); - p->dentry = dget(dentry); - p->dir = parent; - p->owner = sp; - atomic_inc(&sp->so_count); - p->o_arg.fh = NFS_FH(dir); - p->o_arg.open_flags = flags, - p->o_arg.clientid = server->nfs4_state->cl_clientid; - p->o_arg.id = sp->so_id; - p->o_arg.name = &dentry->d_name; - p->o_arg.server = server; - p->o_arg.bitmask = server->attr_bitmask; - p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; - p->o_res.f_attr = &p->f_attr; - p->o_res.dir_attr = &p->dir_attr; - p->o_res.server = server; - nfs_fattr_init(&p->f_attr); - nfs_fattr_init(&p->dir_attr); - if (flags & O_EXCL) { - u32 *s = (u32 *) p->o_arg.u.verifier.data; - s[0] = jiffies; - s[1] = current->pid; - } else if (flags & O_CREAT) { - p->o_arg.u.attrs = &p->attrs; - memcpy(&p->attrs, attrs, sizeof(p->attrs)); - } - p->c_arg.fh = &p->o_res.fh; - p->c_arg.stateid = &p->o_res.stateid; - p->c_arg.seqid = p->o_arg.seqid; - return p; -err_free: - kfree(p); -err: - dput(parent); - return NULL; -} - -static void nfs4_opendata_free(struct nfs4_opendata *p) -{ - if (p != NULL && atomic_dec_and_test(&p->count)) { - nfs_free_seqid(p->o_arg.seqid); - nfs4_put_state_owner(p->owner); - dput(p->dir); - dput(p->dentry); - kfree(p); - } -} - /* Helper for asynchronous RPC calls */ -static int nfs4_call_async(struct rpc_clnt *clnt, - const struct rpc_call_ops *tk_ops, void *calldata) +static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin, + rpc_action tk_exit, void *calldata) { struct rpc_task *task; - if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata))) + if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC))) return -ENOMEM; + + task->tk_calldata = calldata; + task->tk_action = tk_begin; rpc_execute(task); return 0; } -static int nfs4_wait_for_completion_rpc_task(struct rpc_task *task) -{ - sigset_t oldset; - int ret; - - rpc_clnt_sigmask(task->tk_client, &oldset); - ret = rpc_wait_for_completion_task(task); - rpc_clnt_sigunmask(task->tk_client, &oldset); - return ret; -} - -static inline void update_open_stateflags(struct nfs4_state *state, mode_t open_flags) -{ - switch (open_flags) { - case FMODE_WRITE: - state->n_wronly++; - break; - case FMODE_READ: - state->n_rdonly++; - break; - case FMODE_READ|FMODE_WRITE: - state->n_rdwr++; - } -} - static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) { struct inode *inode = state->inode; @@ -321,134 +218,41 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, spin_lock(&state->owner->so_lock); spin_lock(&inode->i_lock); memcpy(&state->stateid, stateid, sizeof(state->stateid)); - update_open_stateflags(state, open_flags); + if ((open_flags & FMODE_WRITE)) + state->nwriters++; + if (open_flags & FMODE_READ) + state->nreaders++; nfs4_state_set_mode_locked(state, state->state | open_flags); spin_unlock(&inode->i_lock); spin_unlock(&state->owner->so_lock); } -static struct nfs4_state *nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data) -{ - struct inode *inode; - struct nfs4_state *state = NULL; - - if (!(data->f_attr.valid & NFS_ATTR_FATTR)) - goto out; - inode = nfs_fhget(data->dir->d_sb, &data->o_res.fh, &data->f_attr); - if (inode == NULL) - goto out; - state = nfs4_get_open_state(inode, data->owner); - if (state == NULL) - goto put_inode; - update_open_stateid(state, &data->o_res.stateid, data->o_arg.open_flags); -put_inode: - iput(inode); -out: - return state; -} - -static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state) -{ - struct nfs_inode *nfsi = NFS_I(state->inode); - struct nfs_open_context *ctx; - - spin_lock(&state->inode->i_lock); - list_for_each_entry(ctx, &nfsi->open_files, list) { - if (ctx->state != state) - continue; - get_nfs_open_context(ctx); - spin_unlock(&state->inode->i_lock); - return ctx; - } - spin_unlock(&state->inode->i_lock); - return ERR_PTR(-ENOENT); -} - -static int nfs4_open_recover_helper(struct nfs4_opendata *opendata, mode_t openflags, nfs4_stateid *stateid) -{ - int ret; - - opendata->o_arg.open_flags = openflags; - ret = _nfs4_proc_open(opendata); - if (ret != 0) - return ret; - memcpy(stateid->data, opendata->o_res.stateid.data, - sizeof(stateid->data)); - return 0; -} - -static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *state) -{ - nfs4_stateid stateid; - struct nfs4_state *newstate; - int mode = 0; - int delegation = 0; - int ret; - - /* memory barrier prior to reading state->n_* */ - smp_rmb(); - if (state->n_rdwr != 0) { - ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &stateid); - if (ret != 0) - return ret; - mode |= FMODE_READ|FMODE_WRITE; - if (opendata->o_res.delegation_type != 0) - delegation = opendata->o_res.delegation_type; - smp_rmb(); - } - if (state->n_wronly != 0) { - ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &stateid); - if (ret != 0) - return ret; - mode |= FMODE_WRITE; - if (opendata->o_res.delegation_type != 0) - delegation = opendata->o_res.delegation_type; - smp_rmb(); - } - if (state->n_rdonly != 0) { - ret = nfs4_open_recover_helper(opendata, FMODE_READ, &stateid); - if (ret != 0) - return ret; - mode |= FMODE_READ; - } - clear_bit(NFS_DELEGATED_STATE, &state->flags); - if (mode == 0) - return 0; - if (opendata->o_res.delegation_type == 0) - opendata->o_res.delegation_type = delegation; - opendata->o_arg.open_flags |= mode; - newstate = nfs4_opendata_to_nfs4_state(opendata); - if (newstate != NULL) { - if (opendata->o_res.delegation_type != 0) { - struct nfs_inode *nfsi = NFS_I(newstate->inode); - int delegation_flags = 0; - if (nfsi->delegation) - delegation_flags = nfsi->delegation->flags; - if (!(delegation_flags & NFS_DELEGATION_NEED_RECLAIM)) - nfs_inode_set_delegation(newstate->inode, - opendata->owner->so_cred, - &opendata->o_res); - else - nfs_inode_reclaim_delegation(newstate->inode, - opendata->owner->so_cred, - &opendata->o_res); - } - nfs4_close_state(newstate, opendata->o_arg.open_flags); - } - if (newstate != state) - return -ESTALE; - return 0; -} - /* * OPEN_RECLAIM: * reclaim state on the server after a reboot. */ -static int _nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry) +static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) { - struct nfs_delegation *delegation = NFS_I(state->inode)->delegation; - struct nfs4_opendata *opendata; - int delegation_type = 0; + struct inode *inode = state->inode; + struct nfs_server *server = NFS_SERVER(inode); + struct nfs_delegation *delegation = NFS_I(inode)->delegation; + struct nfs_openargs o_arg = { + .fh = NFS_FH(inode), + .id = sp->so_id, + .open_flags = state->state, + .clientid = server->nfs4_state->cl_clientid, + .claim = NFS4_OPEN_CLAIM_PREVIOUS, + .bitmask = server->attr_bitmask, + }; + struct nfs_openres o_res = { + .server = server, /* Grrr */ + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR], + .rpc_argp = &o_arg, + .rpc_resp = &o_res, + .rpc_cred = sp->so_cred, + }; int status; if (delegation != NULL) { @@ -458,27 +262,38 @@ static int _nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state set_bit(NFS_DELEGATED_STATE, &state->flags); return 0; } - delegation_type = delegation->type; + o_arg.u.delegation_type = delegation->type; } - opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL); - if (opendata == NULL) + o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); + if (o_arg.seqid == NULL) return -ENOMEM; - opendata->o_arg.claim = NFS4_OPEN_CLAIM_PREVIOUS; - opendata->o_arg.fh = NFS_FH(state->inode); - nfs_copy_fh(&opendata->o_res.fh, opendata->o_arg.fh); - opendata->o_arg.u.delegation_type = delegation_type; - status = nfs4_open_recover(opendata, state); - nfs4_opendata_free(opendata); + status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); + /* Confirm the sequence as being established */ + nfs_confirm_seqid(&sp->so_seqid, status); + nfs_increment_open_seqid(status, o_arg.seqid); + if (status == 0) { + memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); + if (o_res.delegation_type != 0) { + nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res); + /* Did the server issue an immediate delegation recall? */ + if (o_res.do_recall) + nfs_async_inode_return_delegation(inode, &o_res.stateid); + } + } + nfs_free_seqid(o_arg.seqid); + clear_bit(NFS_DELEGATED_STATE, &state->flags); + /* Ensure we update the inode attributes */ + NFS_CACHEINV(inode); return status; } -static int nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry) +static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) { struct nfs_server *server = NFS_SERVER(state->inode); struct nfs4_exception exception = { }; int err; do { - err = _nfs4_do_open_reclaim(sp, state, dentry); + err = _nfs4_open_reclaim(sp, state); if (err != -NFS4ERR_DELAY) break; nfs4_handle_exception(server, err, &exception); @@ -486,36 +301,63 @@ static int nfs4_do_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state * return err; } -static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) -{ - struct nfs_open_context *ctx; - int ret; - - ctx = nfs4_state_find_open_context(state); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - ret = nfs4_do_open_reclaim(sp, state, ctx->dentry); - put_nfs_open_context(ctx); - return ret; -} - static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state) { struct nfs4_state_owner *sp = state->owner; - struct nfs4_opendata *opendata; - int ret; + struct inode *inode = dentry->d_inode; + struct nfs_server *server = NFS_SERVER(inode); + struct dentry *parent = dget_parent(dentry); + struct nfs_openargs arg = { + .fh = NFS_FH(parent->d_inode), + .clientid = server->nfs4_state->cl_clientid, + .name = &dentry->d_name, + .id = sp->so_id, + .server = server, + .bitmask = server->attr_bitmask, + .claim = NFS4_OPEN_CLAIM_DELEGATE_CUR, + }; + struct nfs_openres res = { + .server = server, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR], + .rpc_argp = &arg, + .rpc_resp = &res, + .rpc_cred = sp->so_cred, + }; + int status = 0; if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) - return 0; - opendata = nfs4_opendata_alloc(dentry, sp, 0, NULL); - if (opendata == NULL) - return -ENOMEM; - opendata->o_arg.claim = NFS4_OPEN_CLAIM_DELEGATE_CUR; - memcpy(opendata->o_arg.u.delegation.data, state->stateid.data, - sizeof(opendata->o_arg.u.delegation.data)); - ret = nfs4_open_recover(opendata, state); - nfs4_opendata_free(opendata); - return ret; + goto out; + if (state->state == 0) + goto out; + arg.seqid = nfs_alloc_seqid(&sp->so_seqid); + status = -ENOMEM; + if (arg.seqid == NULL) + goto out; + arg.open_flags = state->state; + memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data)); + status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); + nfs_increment_open_seqid(status, arg.seqid); + if (status != 0) + goto out_free; + if(res.rflags & NFS4_OPEN_RESULT_CONFIRM) { + status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode), + sp, &res.stateid, arg.seqid); + if (status != 0) + goto out_free; + } + nfs_confirm_seqid(&sp->so_seqid, 0); + if (status >= 0) { + memcpy(state->stateid.data, res.stateid.data, + sizeof(state->stateid.data)); + clear_bit(NFS_DELEGATED_STATE, &state->flags); + } +out_free: + nfs_free_seqid(arg.seqid); +out: + dput(parent); + return status; } int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state) @@ -540,202 +382,82 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state) return err; } -static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) +static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid) { - struct nfs4_opendata *data = calldata; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM], - .rpc_argp = &data->c_arg, - .rpc_resp = &data->c_res, - .rpc_cred = data->owner->so_cred, + struct nfs_open_confirmargs arg = { + .fh = fh, + .seqid = seqid, + .stateid = *stateid, + }; + struct nfs_open_confirmres res; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM], + .rpc_argp = &arg, + .rpc_resp = &res, + .rpc_cred = sp->so_cred, }; - data->timestamp = jiffies; - rpc_call_setup(task, &msg, 0); -} - -static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) -{ - struct nfs4_opendata *data = calldata; - - data->rpc_status = task->tk_status; - if (RPC_ASSASSINATED(task)) - return; - if (data->rpc_status == 0) { - memcpy(data->o_res.stateid.data, data->c_res.stateid.data, - sizeof(data->o_res.stateid.data)); - renew_lease(data->o_res.server, data->timestamp); - } - nfs_increment_open_seqid(data->rpc_status, data->c_arg.seqid); - nfs_confirm_seqid(&data->owner->so_seqid, data->rpc_status); -} - -static void nfs4_open_confirm_release(void *calldata) -{ - struct nfs4_opendata *data = calldata; - struct nfs4_state *state = NULL; - - /* If this request hasn't been cancelled, do nothing */ - if (data->cancelled == 0) - goto out_free; - /* In case of error, no cleanup! */ - if (data->rpc_status != 0) - goto out_free; - nfs_confirm_seqid(&data->owner->so_seqid, 0); - state = nfs4_opendata_to_nfs4_state(data); - if (state != NULL) - nfs4_close_state(state, data->o_arg.open_flags); -out_free: - nfs4_opendata_free(data); -} - -static const struct rpc_call_ops nfs4_open_confirm_ops = { - .rpc_call_prepare = nfs4_open_confirm_prepare, - .rpc_call_done = nfs4_open_confirm_done, - .rpc_release = nfs4_open_confirm_release, -}; - -/* - * Note: On error, nfs4_proc_open_confirm will free the struct nfs4_opendata - */ -static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) -{ - struct nfs_server *server = NFS_SERVER(data->dir->d_inode); - struct rpc_task *task; int status; - atomic_inc(&data->count); - task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_confirm_ops, data); - if (IS_ERR(task)) { - nfs4_opendata_free(data); - return PTR_ERR(task); - } - status = nfs4_wait_for_completion_rpc_task(task); - if (status != 0) { - data->cancelled = 1; - smp_wmb(); - } else - status = data->rpc_status; - rpc_release_task(task); + status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR); + /* Confirm the sequence as being established */ + nfs_confirm_seqid(&sp->so_seqid, status); + nfs_increment_open_seqid(status, seqid); + if (status >= 0) + memcpy(stateid, &res.stateid, sizeof(*stateid)); return status; } -static void nfs4_open_prepare(struct rpc_task *task, void *calldata) +static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, struct nfs_openargs *o_arg, struct nfs_openres *o_res) { - struct nfs4_opendata *data = calldata; - struct nfs4_state_owner *sp = data->owner; + struct nfs_server *server = NFS_SERVER(dir); struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN], - .rpc_argp = &data->o_arg, - .rpc_resp = &data->o_res, + .rpc_argp = o_arg, + .rpc_resp = o_res, .rpc_cred = sp->so_cred, }; - - if (nfs_wait_on_sequence(data->o_arg.seqid, task) != 0) - return; - /* Update sequence id. */ - data->o_arg.id = sp->so_id; - data->o_arg.clientid = sp->so_client->cl_clientid; - if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) - msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; - data->timestamp = jiffies; - rpc_call_setup(task, &msg, 0); -} + int status; -static void nfs4_open_done(struct rpc_task *task, void *calldata) -{ - struct nfs4_opendata *data = calldata; + /* Update sequence id. The caller must serialize! */ + o_arg->id = sp->so_id; + o_arg->clientid = sp->so_client->cl_clientid; - data->rpc_status = task->tk_status; - if (RPC_ASSASSINATED(task)) - return; - if (task->tk_status == 0) { - switch (data->o_res.f_attr->mode & S_IFMT) { + status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); + if (status == 0) { + /* OPEN on anything except a regular file is disallowed in NFSv4 */ + switch (o_res->f_attr->mode & S_IFMT) { case S_IFREG: break; case S_IFLNK: - data->rpc_status = -ELOOP; + status = -ELOOP; break; case S_IFDIR: - data->rpc_status = -EISDIR; + status = -EISDIR; break; default: - data->rpc_status = -ENOTDIR; + status = -ENOTDIR; } - renew_lease(data->o_res.server, data->timestamp); } - nfs_increment_open_seqid(data->rpc_status, data->o_arg.seqid); -} - -static void nfs4_open_release(void *calldata) -{ - struct nfs4_opendata *data = calldata; - struct nfs4_state *state = NULL; - /* If this request hasn't been cancelled, do nothing */ - if (data->cancelled == 0) - goto out_free; - /* In case of error, no cleanup! */ - if (data->rpc_status != 0) - goto out_free; - /* In case we need an open_confirm, no cleanup! */ - if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) - goto out_free; - nfs_confirm_seqid(&data->owner->so_seqid, 0); - state = nfs4_opendata_to_nfs4_state(data); - if (state != NULL) - nfs4_close_state(state, data->o_arg.open_flags); -out_free: - nfs4_opendata_free(data); -} - -static const struct rpc_call_ops nfs4_open_ops = { - .rpc_call_prepare = nfs4_open_prepare, - .rpc_call_done = nfs4_open_done, - .rpc_release = nfs4_open_release, -}; - -/* - * Note: On error, nfs4_proc_open will free the struct nfs4_opendata - */ -static int _nfs4_proc_open(struct nfs4_opendata *data) -{ - struct inode *dir = data->dir->d_inode; - struct nfs_server *server = NFS_SERVER(dir); - struct nfs_openargs *o_arg = &data->o_arg; - struct nfs_openres *o_res = &data->o_res; - struct rpc_task *task; - int status; - - atomic_inc(&data->count); - task = rpc_run_task(server->client, RPC_TASK_ASYNC, &nfs4_open_ops, data); - if (IS_ERR(task)) { - nfs4_opendata_free(data); - return PTR_ERR(task); - } - status = nfs4_wait_for_completion_rpc_task(task); - if (status != 0) { - data->cancelled = 1; - smp_wmb(); - } else - status = data->rpc_status; - rpc_release_task(task); + nfs_increment_open_seqid(status, o_arg->seqid); if (status != 0) - return status; - + goto out; if (o_arg->open_flags & O_CREAT) { update_changeattr(dir, &o_res->cinfo); nfs_post_op_update_inode(dir, o_res->dir_attr); } else nfs_refresh_inode(dir, o_res->dir_attr); if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { - status = _nfs4_proc_open_confirm(data); + status = _nfs4_proc_open_confirm(server->client, &o_res->fh, + sp, &o_res->stateid, o_arg->seqid); if (status != 0) - return status; + goto out; } - nfs_confirm_seqid(&data->owner->so_seqid, 0); + nfs_confirm_seqid(&sp->so_seqid, 0); if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) - return server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); - return 0; + status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); +out: + return status; } static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags) @@ -766,15 +488,6 @@ static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openf return -EACCES; } -int nfs4_recover_expired_lease(struct nfs_server *server) -{ - struct nfs4_client *clp = server->nfs4_state; - - if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) - nfs4_schedule_state_recovery(clp); - return nfs4_wait_clnt_recover(server->client, clp); -} - /* * OPEN_EXPIRED: * reclaim state on the server after a network partition. @@ -782,31 +495,77 @@ int nfs4_recover_expired_lease(struct nfs_server *server) */ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry) { + struct dentry *parent = dget_parent(dentry); + struct inode *dir = parent->d_inode; struct inode *inode = state->inode; + struct nfs_server *server = NFS_SERVER(dir); struct nfs_delegation *delegation = NFS_I(inode)->delegation; - struct nfs4_opendata *opendata; - int openflags = state->state & (FMODE_READ|FMODE_WRITE); - int ret; + struct nfs_fattr f_attr, dir_attr; + struct nfs_openargs o_arg = { + .fh = NFS_FH(dir), + .open_flags = state->state, + .name = &dentry->d_name, + .bitmask = server->attr_bitmask, + .claim = NFS4_OPEN_CLAIM_NULL, + }; + struct nfs_openres o_res = { + .f_attr = &f_attr, + .dir_attr = &dir_attr, + .server = server, + }; + int status = 0; if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) { - ret = _nfs4_do_access(inode, sp->so_cred, openflags); - if (ret < 0) - return ret; + status = _nfs4_do_access(inode, sp->so_cred, state->state); + if (status < 0) + goto out; memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid)); set_bit(NFS_DELEGATED_STATE, &state->flags); - return 0; + goto out; } - opendata = nfs4_opendata_alloc(dentry, sp, openflags, NULL); - if (opendata == NULL) - return -ENOMEM; - ret = nfs4_open_recover(opendata, state); - if (ret == -ESTALE) { - /* Invalidate the state owner so we don't ever use it again */ - nfs4_drop_state_owner(sp); - d_drop(dentry); + o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); + status = -ENOMEM; + if (o_arg.seqid == NULL) + goto out; + nfs_fattr_init(&f_attr); + nfs_fattr_init(&dir_attr); + status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); + if (status != 0) + goto out_nodeleg; + /* Check if files differ */ + if ((f_attr.mode & S_IFMT) != (inode->i_mode & S_IFMT)) + goto out_stale; + /* Has the file handle changed? */ + if (nfs_compare_fh(&o_res.fh, NFS_FH(inode)) != 0) { + /* Verify if the change attributes are the same */ + if (f_attr.change_attr != NFS_I(inode)->change_attr) + goto out_stale; + if (nfs_size_to_loff_t(f_attr.size) != inode->i_size) + goto out_stale; + /* Lets just pretend that this is the same file */ + nfs_copy_fh(NFS_FH(inode), &o_res.fh); + NFS_I(inode)->fileid = f_attr.fileid; + } + memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); + if (o_res.delegation_type != 0) { + if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) + nfs_inode_set_delegation(inode, sp->so_cred, &o_res); + else + nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res); } - nfs4_opendata_free(opendata); - return ret; +out_nodeleg: + nfs_free_seqid(o_arg.seqid); + clear_bit(NFS_DELEGATED_STATE, &state->flags); +out: + dput(parent); + return status; +out_stale: + status = -ESTALE; + /* Invalidate the state owner so we don't ever use it again */ + nfs4_drop_state_owner(sp); + d_drop(dentry); + /* Should we be trying to close that stateid? */ + goto out_nodeleg; } static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry) @@ -825,19 +584,26 @@ static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state) { + struct nfs_inode *nfsi = NFS_I(state->inode); struct nfs_open_context *ctx; - int ret; + int status; - ctx = nfs4_state_find_open_context(state); - if (IS_ERR(ctx)) - return PTR_ERR(ctx); - ret = nfs4_do_open_expired(sp, state, ctx->dentry); - put_nfs_open_context(ctx); - return ret; + spin_lock(&state->inode->i_lock); + list_for_each_entry(ctx, &nfsi->open_files, list) { + if (ctx->state != state) + continue; + get_nfs_open_context(ctx); + spin_unlock(&state->inode->i_lock); + status = nfs4_do_open_expired(sp, state, ctx->dentry); + put_nfs_open_context(ctx); + return status; + } + spin_unlock(&state->inode->i_lock); + return -ENOENT; } /* - * Returns a referenced nfs4_state if there is an open delegation on the file + * Returns an nfs4_state + an extra reference to the inode */ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res) { @@ -850,14 +616,6 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred int open_flags = flags & (FMODE_READ|FMODE_WRITE); int err; - err = -ENOMEM; - if (!(sp = nfs4_get_state_owner(server, cred))) { - dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__); - return err; - } - err = nfs4_recover_expired_lease(server); - if (err != 0) - goto out_put_state_owner; /* Protect against reboot recovery - NOTE ORDER! */ down_read(&clp->cl_sem); /* Protect against delegation recall */ @@ -867,6 +625,10 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred if (delegation == NULL || (delegation->type & open_flags) != open_flags) goto out_err; err = -ENOMEM; + if (!(sp = nfs4_get_state_owner(server, cred))) { + dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__); + goto out_err; + } state = nfs4_get_open_state(inode, sp); if (state == NULL) goto out_err; @@ -874,34 +636,39 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred err = -ENOENT; if ((state->state & open_flags) == open_flags) { spin_lock(&inode->i_lock); - update_open_stateflags(state, open_flags); + if (open_flags & FMODE_READ) + state->nreaders++; + if (open_flags & FMODE_WRITE) + state->nwriters++; spin_unlock(&inode->i_lock); goto out_ok; } else if (state->state != 0) - goto out_put_open_state; + goto out_err; lock_kernel(); err = _nfs4_do_access(inode, cred, open_flags); unlock_kernel(); if (err != 0) - goto out_put_open_state; + goto out_err; set_bit(NFS_DELEGATED_STATE, &state->flags); update_open_stateid(state, &delegation->stateid, open_flags); out_ok: nfs4_put_state_owner(sp); up_read(&nfsi->rwsem); up_read(&clp->cl_sem); + igrab(inode); *res = state; - return 0; -out_put_open_state: - nfs4_put_open_state(state); + return 0; out_err: + if (sp != NULL) { + if (state != NULL) + nfs4_put_open_state(state); + nfs4_put_state_owner(sp); + } up_read(&nfsi->rwsem); up_read(&clp->cl_sem); if (err != -EACCES) nfs_inode_return_delegation(inode); -out_put_state_owner: - nfs4_put_state_owner(sp); return err; } @@ -922,7 +689,7 @@ static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, st } /* - * Returns a referenced nfs4_state + * Returns an nfs4_state + an referenced inode */ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res) { @@ -930,46 +697,73 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st struct nfs4_state *state = NULL; struct nfs_server *server = NFS_SERVER(dir); struct nfs4_client *clp = server->nfs4_state; - struct nfs4_opendata *opendata; + struct inode *inode = NULL; int status; + struct nfs_fattr f_attr, dir_attr; + struct nfs_openargs o_arg = { + .fh = NFS_FH(dir), + .open_flags = flags, + .name = &dentry->d_name, + .server = server, + .bitmask = server->attr_bitmask, + .claim = NFS4_OPEN_CLAIM_NULL, + }; + struct nfs_openres o_res = { + .f_attr = &f_attr, + .dir_attr = &dir_attr, + .server = server, + }; /* Protect against reboot recovery conflicts */ + down_read(&clp->cl_sem); status = -ENOMEM; if (!(sp = nfs4_get_state_owner(server, cred))) { dprintk("nfs4_do_open: nfs4_get_state_owner failed!\n"); goto out_err; } - status = nfs4_recover_expired_lease(server); - if (status != 0) - goto err_put_state_owner; - down_read(&clp->cl_sem); - status = -ENOMEM; - opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr); - if (opendata == NULL) - goto err_put_state_owner; + if (flags & O_EXCL) { + u32 *p = (u32 *) o_arg.u.verifier.data; + p[0] = jiffies; + p[1] = current->pid; + } else + o_arg.u.attrs = sattr; + /* Serialization for the sequence id */ - status = _nfs4_proc_open(opendata); + o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); + if (o_arg.seqid == NULL) + return -ENOMEM; + nfs_fattr_init(&f_attr); + nfs_fattr_init(&dir_attr); + status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); if (status != 0) - goto err_opendata_free; + goto out_err; status = -ENOMEM; - state = nfs4_opendata_to_nfs4_state(opendata); - if (state == NULL) - goto err_opendata_free; - if (opendata->o_res.delegation_type != 0) - nfs_inode_set_delegation(state->inode, cred, &opendata->o_res); - nfs4_opendata_free(opendata); + inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr); + if (!inode) + goto out_err; + state = nfs4_get_open_state(inode, sp); + if (!state) + goto out_err; + update_open_stateid(state, &o_res.stateid, flags); + if (o_res.delegation_type != 0) + nfs_inode_set_delegation(inode, cred, &o_res); + nfs_free_seqid(o_arg.seqid); nfs4_put_state_owner(sp); up_read(&clp->cl_sem); *res = state; return 0; -err_opendata_free: - nfs4_opendata_free(opendata); -err_put_state_owner: - nfs4_put_state_owner(sp); out_err: + if (sp != NULL) { + if (state != NULL) + nfs4_put_open_state(state); + nfs_free_seqid(o_arg.seqid); + nfs4_put_state_owner(sp); + } /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */ up_read(&clp->cl_sem); + if (inode != NULL) + iput(inode); *res = NULL; return status; } @@ -1036,7 +830,6 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, .rpc_argp = &arg, .rpc_resp = &res, }; - unsigned long timestamp = jiffies; int status; nfs_fattr_init(fattr); @@ -1048,8 +841,6 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); status = rpc_call_sync(server->client, &msg, 0); - if (status == 0 && state != NULL) - renew_lease(server, timestamp); return status; } @@ -1074,13 +865,12 @@ struct nfs4_closedata { struct nfs_closeargs arg; struct nfs_closeres res; struct nfs_fattr fattr; - unsigned long timestamp; }; -static void nfs4_free_closedata(void *data) +static void nfs4_free_closedata(struct nfs4_closedata *calldata) { - struct nfs4_closedata *calldata = data; - struct nfs4_state_owner *sp = calldata->state->owner; + struct nfs4_state *state = calldata->state; + struct nfs4_state_owner *sp = state->owner; nfs4_put_open_state(calldata->state); nfs_free_seqid(calldata->arg.seqid); @@ -1088,14 +878,12 @@ static void nfs4_free_closedata(void *data) kfree(calldata); } -static void nfs4_close_done(struct rpc_task *task, void *data) +static void nfs4_close_done(struct rpc_task *task) { - struct nfs4_closedata *calldata = data; + struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; struct nfs4_state *state = calldata->state; struct nfs_server *server = NFS_SERVER(calldata->inode); - if (RPC_ASSASSINATED(task)) - return; /* hmm. we are done with the inode, and in the process of freeing * the state_owner. we keep this around to process errors */ @@ -1104,7 +892,6 @@ static void nfs4_close_done(struct rpc_task *task, void *data) case 0: memcpy(&state->stateid, &calldata->res.stateid, sizeof(state->stateid)); - renew_lease(server, calldata->timestamp); break; case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: @@ -1117,11 +904,12 @@ static void nfs4_close_done(struct rpc_task *task, void *data) } } nfs_refresh_inode(calldata->inode, calldata->res.fattr); + nfs4_free_closedata(calldata); } -static void nfs4_close_prepare(struct rpc_task *task, void *data) +static void nfs4_close_begin(struct rpc_task *task) { - struct nfs4_closedata *calldata = data; + struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; struct nfs4_state *state = calldata->state; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], @@ -1130,8 +918,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) .rpc_cred = state->owner->so_cred, }; int mode = 0, old_mode; + int status; - if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) + status = nfs_wait_on_sequence(calldata->arg.seqid, task); + if (status != 0) return; /* Recalculate the new open mode in case someone reopened the file * while we were waiting in line to be scheduled. @@ -1139,34 +929,26 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) spin_lock(&state->owner->so_lock); spin_lock(&calldata->inode->i_lock); mode = old_mode = state->state; - if (state->n_rdwr == 0) { - if (state->n_rdonly == 0) - mode &= ~FMODE_READ; - if (state->n_wronly == 0) - mode &= ~FMODE_WRITE; - } + if (state->nreaders == 0) + mode &= ~FMODE_READ; + if (state->nwriters == 0) + mode &= ~FMODE_WRITE; nfs4_state_set_mode_locked(state, mode); spin_unlock(&calldata->inode->i_lock); spin_unlock(&state->owner->so_lock); if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) { - /* Note: exit _without_ calling nfs4_close_done */ - task->tk_action = NULL; + nfs4_free_closedata(calldata); + task->tk_exit = NULL; + rpc_exit(task, 0); return; } nfs_fattr_init(calldata->res.fattr); if (mode != 0) msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; calldata->arg.open_flags = mode; - calldata->timestamp = jiffies; rpc_call_setup(task, &msg, 0); } -static const struct rpc_call_ops nfs4_close_ops = { - .rpc_call_prepare = nfs4_close_prepare, - .rpc_call_done = nfs4_close_done, - .rpc_release = nfs4_free_closedata, -}; - /* * It is possible for data to be read/written from a mem-mapped file * after the sys_close call (which hits the vfs layer as a flush). @@ -1199,7 +981,8 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state) calldata->res.fattr = &calldata->fattr; calldata->res.server = server; - status = nfs4_call_async(server->client, &nfs4_close_ops, calldata); + status = nfs4_call_async(server->client, nfs4_close_begin, + nfs4_close_done, calldata); if (status == 0) goto out; @@ -1251,7 +1034,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) d_add(dentry, NULL); return (struct dentry *)state; } - res = d_add_unique(dentry, igrab(state->inode)); + res = d_add_unique(dentry, state->inode); if (res != NULL) dentry = res; nfs4_intent_set_file(nd, dentry, state); @@ -1263,6 +1046,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st { struct rpc_cred *cred; struct nfs4_state *state; + struct inode *inode; cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); if (IS_ERR(cred)) @@ -1286,7 +1070,9 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st } goto out_drop; } - if (state->inode == dentry->d_inode) { + inode = state->inode; + iput(inode); + if (inode == dentry->d_inode) { nfs4_intent_set_file(nd, dentry, state); return 1; } @@ -1722,13 +1508,11 @@ static int _nfs4_proc_write(struct nfs_write_data *wdata) wdata->args.bitmask = server->attr_bitmask; wdata->res.server = server; - wdata->timestamp = jiffies; nfs_fattr_init(fattr); status = rpc_call_sync(server->client, &msg, rpcflags); dprintk("NFS reply write: %d\n", status); if (status < 0) return status; - renew_lease(server, wdata->timestamp); nfs_post_op_update_inode(inode, fattr); return wdata->res.count; } @@ -1763,11 +1547,8 @@ static int _nfs4_proc_commit(struct nfs_write_data *cdata) cdata->args.bitmask = server->attr_bitmask; cdata->res.server = server; - cdata->timestamp = jiffies; nfs_fattr_init(fattr); status = rpc_call_sync(server->client, &msg, 0); - if (status >= 0) - renew_lease(server, cdata->timestamp); dprintk("NFS reply commit: %d\n", status); if (status >= 0) nfs_post_op_update_inode(inode, fattr); @@ -1820,7 +1601,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, status = PTR_ERR(state); goto out; } - d_instantiate(dentry, igrab(state->inode)); + d_instantiate(dentry, state->inode); if (flags & O_EXCL) { struct nfs_fattr fattr; status = nfs4_do_setattr(NFS_SERVER(dir), &fattr, @@ -2344,9 +2125,10 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, return err; } -static void nfs4_read_done(struct rpc_task *task, void *calldata) +static void +nfs4_read_done(struct rpc_task *task) { - struct nfs_read_data *data = calldata; + struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; struct inode *inode = data->inode; if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { @@ -2356,14 +2138,9 @@ static void nfs4_read_done(struct rpc_task *task, void *calldata) if (task->tk_status > 0) renew_lease(NFS_SERVER(inode), data->timestamp); /* Call back common NFS readpage processing */ - nfs_readpage_result(task, calldata); + nfs_readpage_result(task); } -static const struct rpc_call_ops nfs4_read_ops = { - .rpc_call_done = nfs4_read_done, - .rpc_release = nfs_readdata_release, -}; - static void nfs4_proc_read_setup(struct nfs_read_data *data) { @@ -2383,13 +2160,14 @@ nfs4_proc_read_setup(struct nfs_read_data *data) flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_read_ops, data); + rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags); rpc_call_setup(task, &msg, 0); } -static void nfs4_write_done(struct rpc_task *task, void *calldata) +static void +nfs4_write_done(struct rpc_task *task) { - struct nfs_write_data *data = calldata; + struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; struct inode *inode = data->inode; if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { @@ -2401,14 +2179,9 @@ static void nfs4_write_done(struct rpc_task *task, void *calldata) nfs_post_op_update_inode(inode, data->res.fattr); } /* Call back common NFS writeback processing */ - nfs_writeback_done(task, calldata); + nfs_writeback_done(task); } -static const struct rpc_call_ops nfs4_write_ops = { - .rpc_call_done = nfs4_write_done, - .rpc_release = nfs_writedata_release, -}; - static void nfs4_proc_write_setup(struct nfs_write_data *data, int how) { @@ -2441,13 +2214,14 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how) flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_write_ops, data); + rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags); rpc_call_setup(task, &msg, 0); } -static void nfs4_commit_done(struct rpc_task *task, void *calldata) +static void +nfs4_commit_done(struct rpc_task *task) { - struct nfs_write_data *data = calldata; + struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; struct inode *inode = data->inode; if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { @@ -2457,14 +2231,9 @@ static void nfs4_commit_done(struct rpc_task *task, void *calldata) if (task->tk_status >= 0) nfs_post_op_update_inode(inode, data->res.fattr); /* Call back common NFS writeback processing */ - nfs_commit_done(task, calldata); + nfs_commit_done(task); } -static const struct rpc_call_ops nfs4_commit_ops = { - .rpc_call_done = nfs4_commit_done, - .rpc_release = nfs_commit_release, -}; - static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how) { @@ -2486,7 +2255,7 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how) flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_commit_ops, data); + rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags); rpc_call_setup(task, &msg, 0); } @@ -2494,10 +2263,11 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how) * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special * standalone procedure for queueing an asynchronous RENEW. */ -static void nfs4_renew_done(struct rpc_task *task, void *data) +static void +renew_done(struct rpc_task *task) { struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; - unsigned long timestamp = (unsigned long)data; + unsigned long timestamp = (unsigned long)task->tk_calldata; if (task->tk_status < 0) { switch (task->tk_status) { @@ -2514,28 +2284,26 @@ static void nfs4_renew_done(struct rpc_task *task, void *data) spin_unlock(&clp->cl_lock); } -static const struct rpc_call_ops nfs4_renew_ops = { - .rpc_call_done = nfs4_renew_done, -}; - -int nfs4_proc_async_renew(struct nfs4_client *clp, struct rpc_cred *cred) +int +nfs4_proc_async_renew(struct nfs4_client *clp) { struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], .rpc_argp = clp, - .rpc_cred = cred, + .rpc_cred = clp->cl_cred, }; return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, - &nfs4_renew_ops, (void *)jiffies); + renew_done, (void *)jiffies); } -int nfs4_proc_renew(struct nfs4_client *clp, struct rpc_cred *cred) +int +nfs4_proc_renew(struct nfs4_client *clp) { struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], .rpc_argp = clp, - .rpc_cred = cred, + .rpc_cred = clp->cl_cred, }; unsigned long now = jiffies; int status; @@ -2751,7 +2519,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) case -NFS4ERR_EXPIRED: rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL, NULL); nfs4_schedule_state_recovery(clp); - if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0) + if (test_bit(NFS4CLNT_OK, &clp->cl_state)) rpc_wake_up_task(task); task->tk_status = 0; return -EAGAIN; @@ -2768,25 +2536,25 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) return 0; } -static int nfs4_wait_bit_interruptible(void *word) -{ - if (signal_pending(current)) - return -ERESTARTSYS; - schedule(); - return 0; -} - static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp) { + DEFINE_WAIT(wait); sigset_t oldset; - int res; + int interruptible, res = 0; might_sleep(); rpc_clnt_sigmask(clnt, &oldset); - res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER, - nfs4_wait_bit_interruptible, - TASK_INTERRUPTIBLE); + interruptible = TASK_UNINTERRUPTIBLE; + if (clnt->cl_intr) + interruptible = TASK_INTERRUPTIBLE; + prepare_to_wait(&clp->cl_waitq, &wait, interruptible); + nfs4_schedule_state_recovery(clp); + if (clnt->cl_intr && signalled()) + res = -ERESTARTSYS; + else if (!test_bit(NFS4CLNT_OK, &clp->cl_state)) + schedule(); + finish_wait(&clp->cl_waitq, &wait); rpc_clnt_sigunmask(clnt, &oldset); return res; } @@ -2829,7 +2597,6 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: - nfs4_schedule_state_recovery(clp); ret = nfs4_wait_clnt_recover(server->client, clp); if (ret == 0) exception->retry = 1; @@ -2846,7 +2613,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct return nfs4_map_errors(ret); } -int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port, struct rpc_cred *cred) +int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port) { nfs4_verifier sc_verifier; struct nfs4_setclientid setclientid = { @@ -2857,7 +2624,7 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID], .rpc_argp = &setclientid, .rpc_resp = clp, - .rpc_cred = cred, + .rpc_cred = clp->cl_cred, }; u32 *p; int loop = 0; @@ -2871,7 +2638,7 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p setclientid.sc_name_len = scnprintf(setclientid.sc_name, sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u", clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr), - cred->cr_ops->cr_name, + clp->cl_cred->cr_ops->cr_name, clp->cl_id_uniquifier); setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, sizeof(setclientid.sc_netid), "tcp"); @@ -2894,14 +2661,14 @@ int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short p } int -nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred) +nfs4_proc_setclientid_confirm(struct nfs4_client *clp) { struct nfs_fsinfo fsinfo; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM], .rpc_argp = clp, .rpc_resp = &fsinfo, - .rpc_cred = cred, + .rpc_cred = clp->cl_cred, }; unsigned long now; int status; @@ -2912,92 +2679,24 @@ nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred) spin_lock(&clp->cl_lock); clp->cl_lease_time = fsinfo.lease_time * HZ; clp->cl_last_renewal = now; - clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); spin_unlock(&clp->cl_lock); } return status; } -struct nfs4_delegreturndata { - struct nfs4_delegreturnargs args; - struct nfs4_delegreturnres res; - struct nfs_fh fh; - nfs4_stateid stateid; - struct rpc_cred *cred; - unsigned long timestamp; - struct nfs_fattr fattr; - int rpc_status; -}; - -static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata) +static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) { - struct nfs4_delegreturndata *data = calldata; + struct nfs4_delegreturnargs args = { + .fhandle = NFS_FH(inode), + .stateid = stateid, + }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN], - .rpc_argp = &data->args, - .rpc_resp = &data->res, - .rpc_cred = data->cred, + .rpc_argp = &args, + .rpc_cred = cred, }; - nfs_fattr_init(data->res.fattr); - rpc_call_setup(task, &msg, 0); -} - -static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) -{ - struct nfs4_delegreturndata *data = calldata; - data->rpc_status = task->tk_status; - if (data->rpc_status == 0) - renew_lease(data->res.server, data->timestamp); -} - -static void nfs4_delegreturn_release(void *calldata) -{ - struct nfs4_delegreturndata *data = calldata; - - put_rpccred(data->cred); - kfree(calldata); -} - -const static struct rpc_call_ops nfs4_delegreturn_ops = { - .rpc_call_prepare = nfs4_delegreturn_prepare, - .rpc_call_done = nfs4_delegreturn_done, - .rpc_release = nfs4_delegreturn_release, -}; -static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) -{ - struct nfs4_delegreturndata *data; - struct nfs_server *server = NFS_SERVER(inode); - struct rpc_task *task; - int status; - - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - data->args.fhandle = &data->fh; - data->args.stateid = &data->stateid; - data->args.bitmask = server->attr_bitmask; - nfs_copy_fh(&data->fh, NFS_FH(inode)); - memcpy(&data->stateid, stateid, sizeof(data->stateid)); - data->res.fattr = &data->fattr; - data->res.server = server; - data->cred = get_rpccred(cred); - data->timestamp = jiffies; - data->rpc_status = 0; - - task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data); - if (IS_ERR(task)) { - nfs4_delegreturn_release(data); - return PTR_ERR(task); - } - status = nfs4_wait_for_completion_rpc_task(task); - if (status == 0) { - status = data->rpc_status; - if (status == 0) - nfs_post_op_update_inode(inode, &data->fattr); - } - rpc_release_task(task); - return status; + return rpc_call_sync(NFS_CLIENT(inode), &msg, 0); } int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) @@ -3035,17 +2734,43 @@ nfs4_set_lock_task_retry(unsigned long timeout) return timeout; } +static inline int +nfs4_lck_type(int cmd, struct file_lock *request) +{ + /* set lock type */ + switch (request->fl_type) { + case F_RDLCK: + return IS_SETLKW(cmd) ? NFS4_READW_LT : NFS4_READ_LT; + case F_WRLCK: + return IS_SETLKW(cmd) ? NFS4_WRITEW_LT : NFS4_WRITE_LT; + case F_UNLCK: + return NFS4_WRITE_LT; + } + BUG(); + return 0; +} + +static inline uint64_t +nfs4_lck_length(struct file_lock *request) +{ + if (request->fl_end == OFFSET_MAX) + return ~(uint64_t)0; + return request->fl_end - request->fl_start + 1; +} + static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request) { struct inode *inode = state->inode; struct nfs_server *server = NFS_SERVER(inode); struct nfs4_client *clp = server->nfs4_state; - struct nfs_lockt_args arg = { + struct nfs_lockargs arg = { .fh = NFS_FH(inode), - .fl = request, + .type = nfs4_lck_type(cmd, request), + .offset = request->fl_start, + .length = nfs4_lck_length(request), }; - struct nfs_lockt_res res = { - .denied = request, + struct nfs_lockres res = { + .server = server, }; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKT], @@ -3053,23 +2778,36 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock .rpc_resp = &res, .rpc_cred = state->owner->so_cred, }; + struct nfs_lowner nlo; struct nfs4_lock_state *lsp; int status; down_read(&clp->cl_sem); - arg.lock_owner.clientid = clp->cl_clientid; + nlo.clientid = clp->cl_clientid; status = nfs4_set_lock_state(state, request); if (status != 0) goto out; lsp = request->fl_u.nfs4_fl.owner; - arg.lock_owner.id = lsp->ls_id; + nlo.id = lsp->ls_id; + arg.u.lockt = &nlo; status = rpc_call_sync(server->client, &msg, 0); - switch (status) { - case 0: - request->fl_type = F_UNLCK; - break; - case -NFS4ERR_DENIED: - status = 0; + if (!status) { + request->fl_type = F_UNLCK; + } else if (status == -NFS4ERR_DENIED) { + int64_t len, start, end; + start = res.u.denied.offset; + len = res.u.denied.length; + end = start + len - 1; + if (end < 0 || len == 0) + request->fl_end = OFFSET_MAX; + else + request->fl_end = (loff_t)end; + request->fl_start = (loff_t)start; + request->fl_type = F_WRLCK; + if (res.u.denied.type & 1) + request->fl_type = F_RDLCK; + request->fl_pid = 0; + status = 0; } out: up_read(&clp->cl_sem); @@ -3109,314 +2847,196 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) } struct nfs4_unlockdata { - struct nfs_locku_args arg; - struct nfs_locku_res res; + struct nfs_lockargs arg; + struct nfs_locku_opargs luargs; + struct nfs_lockres res; struct nfs4_lock_state *lsp; struct nfs_open_context *ctx; - struct file_lock fl; - const struct nfs_server *server; - unsigned long timestamp; + atomic_t refcount; + struct completion completion; }; -static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, - struct nfs_open_context *ctx, - struct nfs4_lock_state *lsp, - struct nfs_seqid *seqid) -{ - struct nfs4_unlockdata *p; - struct inode *inode = lsp->ls_state->inode; - - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (p == NULL) - return NULL; - p->arg.fh = NFS_FH(inode); - p->arg.fl = &p->fl; - p->arg.seqid = seqid; - p->arg.stateid = &lsp->ls_stateid; - p->lsp = lsp; - atomic_inc(&lsp->ls_count); - /* Ensure we don't close file until we're done freeing locks! */ - p->ctx = get_nfs_open_context(ctx); - memcpy(&p->fl, fl, sizeof(p->fl)); - p->server = NFS_SERVER(inode); - return p; +static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata) +{ + if (atomic_dec_and_test(&calldata->refcount)) { + nfs_free_seqid(calldata->luargs.seqid); + nfs4_put_lock_state(calldata->lsp); + put_nfs_open_context(calldata->ctx); + kfree(calldata); + } } -static void nfs4_locku_release_calldata(void *data) +static void nfs4_locku_complete(struct nfs4_unlockdata *calldata) { - struct nfs4_unlockdata *calldata = data; - nfs_free_seqid(calldata->arg.seqid); - nfs4_put_lock_state(calldata->lsp); - put_nfs_open_context(calldata->ctx); - kfree(calldata); + complete(&calldata->completion); + nfs4_locku_release_calldata(calldata); } -static void nfs4_locku_done(struct rpc_task *task, void *data) +static void nfs4_locku_done(struct rpc_task *task) { - struct nfs4_unlockdata *calldata = data; + struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata; - if (RPC_ASSASSINATED(task)) - return; - nfs_increment_lock_seqid(task->tk_status, calldata->arg.seqid); + nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid); switch (task->tk_status) { case 0: memcpy(calldata->lsp->ls_stateid.data, - calldata->res.stateid.data, + calldata->res.u.stateid.data, sizeof(calldata->lsp->ls_stateid.data)); - renew_lease(calldata->server, calldata->timestamp); break; case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: - nfs4_schedule_state_recovery(calldata->server->nfs4_state); + nfs4_schedule_state_recovery(calldata->res.server->nfs4_state); break; default: - if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN) { + if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) { rpc_restart_call(task); + return; } } + nfs4_locku_complete(calldata); } -static void nfs4_locku_prepare(struct rpc_task *task, void *data) +static void nfs4_locku_begin(struct rpc_task *task) { - struct nfs4_unlockdata *calldata = data; + struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], .rpc_argp = &calldata->arg, .rpc_resp = &calldata->res, .rpc_cred = calldata->lsp->ls_state->owner->so_cred, }; + int status; - if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) + status = nfs_wait_on_sequence(calldata->luargs.seqid, task); + if (status != 0) return; if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) { - /* Note: exit _without_ running nfs4_locku_done */ - task->tk_action = NULL; + nfs4_locku_complete(calldata); + task->tk_exit = NULL; + rpc_exit(task, 0); return; } - calldata->timestamp = jiffies; rpc_call_setup(task, &msg, 0); } -static const struct rpc_call_ops nfs4_locku_ops = { - .rpc_call_prepare = nfs4_locku_prepare, - .rpc_call_done = nfs4_locku_done, - .rpc_release = nfs4_locku_release_calldata, -}; - -static struct rpc_task *nfs4_do_unlck(struct file_lock *fl, - struct nfs_open_context *ctx, - struct nfs4_lock_state *lsp, - struct nfs_seqid *seqid) -{ - struct nfs4_unlockdata *data; - struct rpc_task *task; - - data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid); - if (data == NULL) { - nfs_free_seqid(seqid); - return ERR_PTR(-ENOMEM); - } - - /* Unlock _before_ we do the RPC call */ - do_vfs_lock(fl->fl_file, fl); - task = rpc_run_task(NFS_CLIENT(lsp->ls_state->inode), RPC_TASK_ASYNC, &nfs4_locku_ops, data); - if (IS_ERR(task)) - nfs4_locku_release_calldata(data); - return task; -} - static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) { - struct nfs_seqid *seqid; + struct nfs4_unlockdata *calldata; + struct inode *inode = state->inode; + struct nfs_server *server = NFS_SERVER(inode); struct nfs4_lock_state *lsp; - struct rpc_task *task; - int status = 0; + int status; /* Is this a delegated lock? */ if (test_bit(NFS_DELEGATED_STATE, &state->flags)) - goto out_unlock; - /* Is this open_owner holding any locks on the server? */ - if (test_bit(LK_STATE_IN_USE, &state->flags) == 0) - goto out_unlock; + return do_vfs_lock(request->fl_file, request); status = nfs4_set_lock_state(state, request); if (status != 0) - goto out_unlock; + return status; lsp = request->fl_u.nfs4_fl.owner; - status = -ENOMEM; - seqid = nfs_alloc_seqid(&lsp->ls_seqid); - if (seqid == NULL) - goto out_unlock; - task = nfs4_do_unlck(request, request->fl_file->private_data, lsp, seqid); - status = PTR_ERR(task); - if (IS_ERR(task)) - goto out_unlock; - status = nfs4_wait_for_completion_rpc_task(task); - rpc_release_task(task); - return status; -out_unlock: - do_vfs_lock(request->fl_file, request); - return status; -} - -struct nfs4_lockdata { - struct nfs_lock_args arg; - struct nfs_lock_res res; - struct nfs4_lock_state *lsp; - struct nfs_open_context *ctx; - struct file_lock fl; - unsigned long timestamp; - int rpc_status; - int cancelled; -}; + /* We might have lost the locks! */ + if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) + return 0; + calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); + if (calldata == NULL) + return -ENOMEM; + calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid); + if (calldata->luargs.seqid == NULL) { + kfree(calldata); + return -ENOMEM; + } + calldata->luargs.stateid = &lsp->ls_stateid; + calldata->arg.fh = NFS_FH(inode); + calldata->arg.type = nfs4_lck_type(cmd, request); + calldata->arg.offset = request->fl_start; + calldata->arg.length = nfs4_lck_length(request); + calldata->arg.u.locku = &calldata->luargs; + calldata->res.server = server; + calldata->lsp = lsp; + atomic_inc(&lsp->ls_count); -static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, - struct nfs_open_context *ctx, struct nfs4_lock_state *lsp) -{ - struct nfs4_lockdata *p; - struct inode *inode = lsp->ls_state->inode; - struct nfs_server *server = NFS_SERVER(inode); + /* Ensure we don't close file until we're done freeing locks! */ + calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data); - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (p == NULL) - return NULL; + atomic_set(&calldata->refcount, 2); + init_completion(&calldata->completion); - p->arg.fh = NFS_FH(inode); - p->arg.fl = &p->fl; - p->arg.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); - if (p->arg.lock_seqid == NULL) - goto out_free; - p->arg.lock_stateid = &lsp->ls_stateid; - p->arg.lock_owner.clientid = server->nfs4_state->cl_clientid; - p->arg.lock_owner.id = lsp->ls_id; - p->lsp = lsp; - atomic_inc(&lsp->ls_count); - p->ctx = get_nfs_open_context(ctx); - memcpy(&p->fl, fl, sizeof(p->fl)); - return p; -out_free: - kfree(p); - return NULL; + status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin, + nfs4_locku_done, calldata); + if (status == 0) + wait_for_completion_interruptible(&calldata->completion); + do_vfs_lock(request->fl_file, request); + nfs4_locku_release_calldata(calldata); + return status; } -static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) +static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim) { - struct nfs4_lockdata *data = calldata; - struct nfs4_state *state = data->lsp->ls_state; - struct nfs4_state_owner *sp = state->owner; + struct inode *inode = state->inode; + struct nfs_server *server = NFS_SERVER(inode); + struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner; + struct nfs_lock_opargs largs = { + .lock_stateid = &lsp->ls_stateid, + .open_stateid = &state->stateid, + .lock_owner = { + .clientid = server->nfs4_state->cl_clientid, + .id = lsp->ls_id, + }, + .reclaim = reclaim, + }; + struct nfs_lockargs arg = { + .fh = NFS_FH(inode), + .type = nfs4_lck_type(cmd, request), + .offset = request->fl_start, + .length = nfs4_lck_length(request), + .u = { + .lock = &largs, + }, + }; + struct nfs_lockres res = { + .server = server, + }; struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], - .rpc_argp = &data->arg, - .rpc_resp = &data->res, - .rpc_cred = sp->so_cred, + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK], + .rpc_argp = &arg, + .rpc_resp = &res, + .rpc_cred = state->owner->so_cred, }; + int status = -ENOMEM; - if (nfs_wait_on_sequence(data->arg.lock_seqid, task) != 0) - return; - dprintk("%s: begin!\n", __FUNCTION__); - /* Do we need to do an open_to_lock_owner? */ - if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { - data->arg.open_seqid = nfs_alloc_seqid(&sp->so_seqid); - if (data->arg.open_seqid == NULL) { - data->rpc_status = -ENOMEM; - task->tk_action = NULL; - goto out; - } - data->arg.open_stateid = &state->stateid; - data->arg.new_lock_owner = 1; - } - data->timestamp = jiffies; - rpc_call_setup(task, &msg, 0); -out: - dprintk("%s: done!, ret = %d\n", __FUNCTION__, data->rpc_status); -} - -static void nfs4_lock_done(struct rpc_task *task, void *calldata) -{ - struct nfs4_lockdata *data = calldata; - - dprintk("%s: begin!\n", __FUNCTION__); + largs.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); + if (largs.lock_seqid == NULL) + return -ENOMEM; + if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) { + struct nfs4_state_owner *owner = state->owner; - data->rpc_status = task->tk_status; - if (RPC_ASSASSINATED(task)) - goto out; - if (data->arg.new_lock_owner != 0) { - nfs_increment_open_seqid(data->rpc_status, data->arg.open_seqid); - if (data->rpc_status == 0) - nfs_confirm_seqid(&data->lsp->ls_seqid, 0); - else + largs.open_seqid = nfs_alloc_seqid(&owner->so_seqid); + if (largs.open_seqid == NULL) goto out; - } - if (data->rpc_status == 0) { - memcpy(data->lsp->ls_stateid.data, data->res.stateid.data, - sizeof(data->lsp->ls_stateid.data)); - data->lsp->ls_flags |= NFS_LOCK_INITIALIZED; - renew_lease(NFS_SERVER(data->ctx->dentry->d_inode), data->timestamp); - } - nfs_increment_lock_seqid(data->rpc_status, data->arg.lock_seqid); -out: - dprintk("%s: done, ret = %d!\n", __FUNCTION__, data->rpc_status); -} - -static void nfs4_lock_release(void *calldata) -{ - struct nfs4_lockdata *data = calldata; - - dprintk("%s: begin!\n", __FUNCTION__); - if (data->arg.open_seqid != NULL) - nfs_free_seqid(data->arg.open_seqid); - if (data->cancelled != 0) { - struct rpc_task *task; - task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, - data->arg.lock_seqid); - if (!IS_ERR(task)) - rpc_release_task(task); - dprintk("%s: cancelling lock!\n", __FUNCTION__); - } else - nfs_free_seqid(data->arg.lock_seqid); - nfs4_put_lock_state(data->lsp); - put_nfs_open_context(data->ctx); - kfree(data); - dprintk("%s: done!\n", __FUNCTION__); -} - -static const struct rpc_call_ops nfs4_lock_ops = { - .rpc_call_prepare = nfs4_lock_prepare, - .rpc_call_done = nfs4_lock_done, - .rpc_release = nfs4_lock_release, -}; - -static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *fl, int reclaim) -{ - struct nfs4_lockdata *data; - struct rpc_task *task; - int ret; - - dprintk("%s: begin!\n", __FUNCTION__); - data = nfs4_alloc_lockdata(fl, fl->fl_file->private_data, - fl->fl_u.nfs4_fl.owner); - if (data == NULL) - return -ENOMEM; - if (IS_SETLKW(cmd)) - data->arg.block = 1; - if (reclaim != 0) - data->arg.reclaim = 1; - task = rpc_run_task(NFS_CLIENT(state->inode), RPC_TASK_ASYNC, - &nfs4_lock_ops, data); - if (IS_ERR(task)) { - nfs4_lock_release(data); - return PTR_ERR(task); - } - ret = nfs4_wait_for_completion_rpc_task(task); - if (ret == 0) { - ret = data->rpc_status; - if (ret == -NFS4ERR_DENIED) - ret = -EAGAIN; + largs.new_lock_owner = 1; + status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); + /* increment open seqid on success, and seqid mutating errors */ + if (largs.new_lock_owner != 0) { + nfs_increment_open_seqid(status, largs.open_seqid); + if (status == 0) + nfs_confirm_seqid(&lsp->ls_seqid, 0); + } + nfs_free_seqid(largs.open_seqid); } else - data->cancelled = 1; - rpc_release_task(task); - dprintk("%s: done, ret = %d!\n", __FUNCTION__, ret); - return ret; + status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); + /* increment lock seqid on success, and seqid mutating errors*/ + nfs_increment_lock_seqid(status, largs.lock_seqid); + /* save the returned stateid. */ + if (status == 0) { + memcpy(lsp->ls_stateid.data, res.u.stateid.data, + sizeof(lsp->ls_stateid.data)); + lsp->ls_flags |= NFS_LOCK_INITIALIZED; + } else if (status == -NFS4ERR_DENIED) + status = -EAGAIN; +out: + nfs_free_seqid(largs.lock_seqid); + return status; } static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) diff --git a/trunk/fs/nfs/nfs4renewd.c b/trunk/fs/nfs/nfs4renewd.c index 5d764d8e6d8a..a3001628ad32 100644 --- a/trunk/fs/nfs/nfs4renewd.c +++ b/trunk/fs/nfs/nfs4renewd.c @@ -54,7 +54,6 @@ #include #include #include "nfs4_fs.h" -#include "delegation.h" #define NFSDBG_FACILITY NFSDBG_PROC @@ -62,7 +61,6 @@ void nfs4_renew_state(void *data) { struct nfs4_client *clp = (struct nfs4_client *)data; - struct rpc_cred *cred; long lease, timeout; unsigned long last, now; @@ -70,7 +68,7 @@ nfs4_renew_state(void *data) dprintk("%s: start\n", __FUNCTION__); /* Are there any active superblocks? */ if (list_empty(&clp->cl_superblocks)) - goto out; + goto out; spin_lock(&clp->cl_lock); lease = clp->cl_lease_time; last = clp->cl_last_renewal; @@ -78,17 +76,9 @@ nfs4_renew_state(void *data) timeout = (2 * lease) / 3 + (long)last - (long)now; /* Are we close to a lease timeout? */ if (time_after(now, last + lease/3)) { - cred = nfs4_get_renew_cred(clp); - if (cred == NULL) { - set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); - spin_unlock(&clp->cl_lock); - nfs_expire_all_delegations(clp); - goto out; - } spin_unlock(&clp->cl_lock); /* Queue an asynchronous RENEW. */ - nfs4_proc_async_renew(clp, cred); - put_rpccred(cred); + nfs4_proc_async_renew(clp); timeout = (2 * lease) / 3; spin_lock(&clp->cl_lock); } else diff --git a/trunk/fs/nfs/nfs4state.c b/trunk/fs/nfs/nfs4state.c index afad0255e7db..5ef4c57618fe 100644 --- a/trunk/fs/nfs/nfs4state.c +++ b/trunk/fs/nfs/nfs4state.c @@ -43,8 +43,6 @@ #include #include #include -#include -#include #include #include @@ -59,6 +57,8 @@ const nfs4_stateid zero_stateid; static DEFINE_SPINLOCK(state_spinlock); static LIST_HEAD(nfs4_clientid_list); +static void nfs4_recover_state(void *); + void init_nfsv4_state(struct nfs_server *server) { @@ -91,10 +91,11 @@ nfs4_alloc_client(struct in_addr *addr) if (nfs_callback_up() < 0) return NULL; - if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) { + if ((clp = kmalloc(sizeof(*clp), GFP_KERNEL)) == NULL) { nfs_callback_down(); return NULL; } + memset(clp, 0, sizeof(*clp)); memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); init_rwsem(&clp->cl_sem); INIT_LIST_HEAD(&clp->cl_delegations); @@ -102,12 +103,14 @@ nfs4_alloc_client(struct in_addr *addr) INIT_LIST_HEAD(&clp->cl_unused); spin_lock_init(&clp->cl_lock); atomic_set(&clp->cl_count, 1); + INIT_WORK(&clp->cl_recoverd, nfs4_recover_state, clp); INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); INIT_LIST_HEAD(&clp->cl_superblocks); + init_waitqueue_head(&clp->cl_waitq); rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); clp->cl_rpcclient = ERR_PTR(-EINVAL); clp->cl_boot_time = CURRENT_TIME; - clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; + clp->cl_state = 1 << NFS4CLNT_OK; return clp; } @@ -124,6 +127,8 @@ nfs4_free_client(struct nfs4_client *clp) kfree(sp); } BUG_ON(!list_empty(&clp->cl_state_owners)); + if (clp->cl_cred) + put_rpccred(clp->cl_cred); nfs_idmap_delete(clp); if (!IS_ERR(clp->cl_rpcclient)) rpc_shutdown_client(clp->cl_rpcclient); @@ -188,22 +193,27 @@ nfs4_put_client(struct nfs4_client *clp) list_del(&clp->cl_servers); spin_unlock(&state_spinlock); BUG_ON(!list_empty(&clp->cl_superblocks)); + wake_up_all(&clp->cl_waitq); rpc_wake_up(&clp->cl_rpcwaitq); nfs4_kill_renewd(clp); nfs4_free_client(clp); } -static int nfs4_init_client(struct nfs4_client *clp, struct rpc_cred *cred) +static int __nfs4_init_client(struct nfs4_client *clp) { - int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, - nfs_callback_tcpport, cred); + int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, nfs_callback_tcpport); if (status == 0) - status = nfs4_proc_setclientid_confirm(clp, cred); + status = nfs4_proc_setclientid_confirm(clp); if (status == 0) nfs4_schedule_state_renewal(clp); return status; } +int nfs4_init_client(struct nfs4_client *clp) +{ + return nfs4_map_errors(__nfs4_init_client(clp)); +} + u32 nfs4_alloc_lockowner_id(struct nfs4_client *clp) { @@ -225,32 +235,6 @@ nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred) return sp; } -struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp) -{ - struct nfs4_state_owner *sp; - struct rpc_cred *cred = NULL; - - list_for_each_entry(sp, &clp->cl_state_owners, so_list) { - if (list_empty(&sp->so_states)) - continue; - cred = get_rpccred(sp->so_cred); - break; - } - return cred; -} - -struct rpc_cred *nfs4_get_setclientid_cred(struct nfs4_client *clp) -{ - struct nfs4_state_owner *sp; - - if (!list_empty(&clp->cl_state_owners)) { - sp = list_entry(clp->cl_state_owners.next, - struct nfs4_state_owner, so_list); - return get_rpccred(sp->so_cred); - } - return NULL; -} - static struct nfs4_state_owner * nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred) { @@ -365,9 +349,14 @@ nfs4_alloc_open_state(void) { struct nfs4_state *state; - state = kzalloc(sizeof(*state), GFP_KERNEL); + state = kmalloc(sizeof(*state), GFP_KERNEL); if (!state) return NULL; + state->state = 0; + state->nreaders = 0; + state->nwriters = 0; + state->flags = 0; + memset(state->stateid.data, 0, sizeof(state->stateid.data)); atomic_set(&state->count, 1); INIT_LIST_HEAD(&state->lock_states); spin_lock_init(&state->state_lock); @@ -486,23 +475,15 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode) /* Protect against nfs4_find_state() */ spin_lock(&owner->so_lock); spin_lock(&inode->i_lock); - switch (mode & (FMODE_READ | FMODE_WRITE)) { - case FMODE_READ: - state->n_rdonly--; - break; - case FMODE_WRITE: - state->n_wronly--; - break; - case FMODE_READ|FMODE_WRITE: - state->n_rdwr--; - } + if (mode & FMODE_READ) + state->nreaders--; + if (mode & FMODE_WRITE) + state->nwriters--; oldstate = newstate = state->state; - if (state->n_rdwr == 0) { - if (state->n_rdonly == 0) - newstate &= ~FMODE_READ; - if (state->n_wronly == 0) - newstate &= ~FMODE_WRITE; - } + if (state->nreaders == 0) + newstate &= ~FMODE_READ; + if (state->nwriters == 0) + newstate &= ~FMODE_WRITE; if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { nfs4_state_set_mode_locked(state, newstate); oldstate = newstate; @@ -752,43 +733,45 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) } static int reclaimer(void *); - -static inline void nfs4_clear_recover_bit(struct nfs4_client *clp) -{ - smp_mb__before_clear_bit(); - clear_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state); - smp_mb__after_clear_bit(); - wake_up_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER); - rpc_wake_up(&clp->cl_rpcwaitq); -} +struct reclaimer_args { + struct nfs4_client *clp; + struct completion complete; +}; /* * State recovery routine */ -static void nfs4_recover_state(struct nfs4_client *clp) +void +nfs4_recover_state(void *data) { - struct task_struct *task; + struct nfs4_client *clp = (struct nfs4_client *)data; + struct reclaimer_args args = { + .clp = clp, + }; + might_sleep(); - __module_get(THIS_MODULE); - atomic_inc(&clp->cl_count); - task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim", - NIPQUAD(clp->cl_addr)); - if (!IS_ERR(task)) - return; - nfs4_clear_recover_bit(clp); - nfs4_put_client(clp); - module_put(THIS_MODULE); + init_completion(&args.complete); + + if (kernel_thread(reclaimer, &args, CLONE_KERNEL) < 0) + goto out_failed_clear; + wait_for_completion(&args.complete); + return; +out_failed_clear: + set_bit(NFS4CLNT_OK, &clp->cl_state); + wake_up_all(&clp->cl_waitq); + rpc_wake_up(&clp->cl_rpcwaitq); } /* * Schedule a state recovery attempt */ -void nfs4_schedule_state_recovery(struct nfs4_client *clp) +void +nfs4_schedule_state_recovery(struct nfs4_client *clp) { if (!clp) return; - if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0) - nfs4_recover_state(clp); + if (test_and_clear_bit(NFS4CLNT_OK, &clp->cl_state)) + schedule_work(&clp->cl_recoverd); } static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_state *state) @@ -904,14 +887,18 @@ static void nfs4_state_mark_reclaim(struct nfs4_client *clp) static int reclaimer(void *ptr) { - struct nfs4_client *clp = ptr; + struct reclaimer_args *args = (struct reclaimer_args *)ptr; + struct nfs4_client *clp = args->clp; struct nfs4_state_owner *sp; struct nfs4_state_recovery_ops *ops; - struct rpc_cred *cred; int status = 0; + daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr)); allow_signal(SIGKILL); + atomic_inc(&clp->cl_count); + complete(&args->complete); + /* Ensure exclusive access to NFSv4 state */ lock_kernel(); down_write(&clp->cl_sem); @@ -919,33 +906,20 @@ static int reclaimer(void *ptr) if (list_empty(&clp->cl_superblocks)) goto out; restart_loop: - ops = &nfs4_network_partition_recovery_ops; - /* Are there any open files on this volume? */ - cred = nfs4_get_renew_cred(clp); - if (cred != NULL) { - /* Yes there are: try to renew the old lease */ - status = nfs4_proc_renew(clp, cred); - switch (status) { - case 0: - case -NFS4ERR_CB_PATH_DOWN: - put_rpccred(cred); - goto out; - case -NFS4ERR_STALE_CLIENTID: - case -NFS4ERR_LEASE_MOVED: - ops = &nfs4_reboot_recovery_ops; - } - } else { - /* "reboot" to ensure we clear all state on the server */ - clp->cl_boot_time = CURRENT_TIME; - cred = nfs4_get_setclientid_cred(clp); - } - /* We're going to have to re-establish a clientid */ + status = nfs4_proc_renew(clp); + switch (status) { + case 0: + case -NFS4ERR_CB_PATH_DOWN: + goto out; + case -NFS4ERR_STALE_CLIENTID: + case -NFS4ERR_LEASE_MOVED: + ops = &nfs4_reboot_recovery_ops; + break; + default: + ops = &nfs4_network_partition_recovery_ops; + }; nfs4_state_mark_reclaim(clp); - status = -ENOENT; - if (cred != NULL) { - status = nfs4_init_client(clp, cred); - put_rpccred(cred); - } + status = __nfs4_init_client(clp); if (status) goto out_error; /* Mark all delegations for reclaim */ @@ -966,13 +940,14 @@ static int reclaimer(void *ptr) } nfs_delegation_reap_unclaimed(clp); out: + set_bit(NFS4CLNT_OK, &clp->cl_state); up_write(&clp->cl_sem); unlock_kernel(); + wake_up_all(&clp->cl_waitq); + rpc_wake_up(&clp->cl_rpcwaitq); if (status == -NFS4ERR_CB_PATH_DOWN) nfs_handle_cb_pathdown(clp); - nfs4_clear_recover_bit(clp); nfs4_put_client(clp); - module_put_and_exit(0); return 0; out_error: printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n", diff --git a/trunk/fs/nfs/nfs4xdr.c b/trunk/fs/nfs/nfs4xdr.c index 4bbf5ef57785..fbbace8a30c4 100644 --- a/trunk/fs/nfs/nfs4xdr.c +++ b/trunk/fs/nfs/nfs4xdr.c @@ -392,11 +392,9 @@ static int nfs_stat_to_errno(int); decode_getattr_maxsz) #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ encode_putfh_maxsz + \ - encode_delegreturn_maxsz + \ - encode_getattr_maxsz) + encode_delegreturn_maxsz) #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ - decode_delegreturn_maxsz + \ - decode_getattr_maxsz) + decode_delegreturn_maxsz) #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ encode_putfh_maxsz + \ encode_getattr_maxsz) @@ -566,7 +564,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s } if (iap->ia_valid & ATTR_MODE) { bmval1 |= FATTR4_WORD1_MODE; - WRITE32(iap->ia_mode & S_IALLUGO); + WRITE32(iap->ia_mode); } if (iap->ia_valid & ATTR_UID) { bmval1 |= FATTR4_WORD1_OWNER; @@ -744,80 +742,69 @@ static int encode_link(struct xdr_stream *xdr, const struct qstr *name) return 0; } -static inline int nfs4_lock_type(struct file_lock *fl, int block) -{ - if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) - return block ? NFS4_READW_LT : NFS4_READ_LT; - return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT; -} - -static inline uint64_t nfs4_lock_length(struct file_lock *fl) -{ - if (fl->fl_end == OFFSET_MAX) - return ~(uint64_t)0; - return fl->fl_end - fl->fl_start + 1; -} - /* * opcode,type,reclaim,offset,length,new_lock_owner = 32 * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 */ -static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args) +static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg) { uint32_t *p; + struct nfs_lock_opargs *opargs = arg->u.lock; RESERVE_SPACE(32); WRITE32(OP_LOCK); - WRITE32(nfs4_lock_type(args->fl, args->block)); - WRITE32(args->reclaim); - WRITE64(args->fl->fl_start); - WRITE64(nfs4_lock_length(args->fl)); - WRITE32(args->new_lock_owner); - if (args->new_lock_owner){ + WRITE32(arg->type); + WRITE32(opargs->reclaim); + WRITE64(arg->offset); + WRITE64(arg->length); + WRITE32(opargs->new_lock_owner); + if (opargs->new_lock_owner){ RESERVE_SPACE(40); - WRITE32(args->open_seqid->sequence->counter); - WRITEMEM(args->open_stateid->data, sizeof(args->open_stateid->data)); - WRITE32(args->lock_seqid->sequence->counter); - WRITE64(args->lock_owner.clientid); + WRITE32(opargs->open_seqid->sequence->counter); + WRITEMEM(opargs->open_stateid->data, sizeof(opargs->open_stateid->data)); + WRITE32(opargs->lock_seqid->sequence->counter); + WRITE64(opargs->lock_owner.clientid); WRITE32(4); - WRITE32(args->lock_owner.id); + WRITE32(opargs->lock_owner.id); } else { RESERVE_SPACE(20); - WRITEMEM(args->lock_stateid->data, sizeof(args->lock_stateid->data)); - WRITE32(args->lock_seqid->sequence->counter); + WRITEMEM(opargs->lock_stateid->data, sizeof(opargs->lock_stateid->data)); + WRITE32(opargs->lock_seqid->sequence->counter); } return 0; } -static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args) +static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockargs *arg) { uint32_t *p; + struct nfs_lowner *opargs = arg->u.lockt; RESERVE_SPACE(40); WRITE32(OP_LOCKT); - WRITE32(nfs4_lock_type(args->fl, 0)); - WRITE64(args->fl->fl_start); - WRITE64(nfs4_lock_length(args->fl)); - WRITE64(args->lock_owner.clientid); + WRITE32(arg->type); + WRITE64(arg->offset); + WRITE64(arg->length); + WRITE64(opargs->clientid); WRITE32(4); - WRITE32(args->lock_owner.id); + WRITE32(opargs->id); return 0; } -static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args) +static int encode_locku(struct xdr_stream *xdr, const struct nfs_lockargs *arg) { uint32_t *p; + struct nfs_locku_opargs *opargs = arg->u.locku; RESERVE_SPACE(44); WRITE32(OP_LOCKU); - WRITE32(nfs4_lock_type(args->fl, 0)); - WRITE32(args->seqid->sequence->counter); - WRITEMEM(args->stateid->data, sizeof(args->stateid->data)); - WRITE64(args->fl->fl_start); - WRITE64(nfs4_lock_length(args->fl)); + WRITE32(arg->type); + WRITE32(opargs->seqid->sequence->counter); + WRITEMEM(opargs->stateid->data, sizeof(opargs->stateid->data)); + WRITE64(arg->offset); + WRITE64(arg->length); return 0; } @@ -977,9 +964,9 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con { uint32_t *p; - RESERVE_SPACE(8+sizeof(arg->stateid->data)); + RESERVE_SPACE(8+sizeof(arg->stateid.data)); WRITE32(OP_OPEN_CONFIRM); - WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data)); + WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); WRITE32(arg->seqid->sequence->counter); return 0; @@ -1512,6 +1499,9 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena }; int status; + status = nfs_wait_on_sequence(args->seqid, req->rq_task); + if (status != 0) + goto out; xdr_init_encode(&xdr, &req->rq_snd_buf, p); encode_compound_hdr(&xdr, &hdr); status = encode_putfh(&xdr, args->fh); @@ -1548,6 +1538,9 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n }; int status; + status = nfs_wait_on_sequence(args->seqid, req->rq_task); + if (status != 0) + goto out; xdr_init_encode(&xdr, &req->rq_snd_buf, p); encode_compound_hdr(&xdr, &hdr); status = encode_putfh(&xdr, args->fh); @@ -1565,19 +1558,19 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nf { struct xdr_stream xdr; struct compound_hdr hdr = { - .nops = 3, + .nops = 2, }; int status; + status = nfs_wait_on_sequence(args->seqid, req->rq_task); + if (status != 0) + goto out; xdr_init_encode(&xdr, &req->rq_snd_buf, p); encode_compound_hdr(&xdr, &hdr); status = encode_putfh(&xdr, args->fh); if (status) goto out; status = encode_open(&xdr, args); - if (status) - goto out; - status = encode_getfattr(&xdr, args->bitmask); out: return status; } @@ -1609,14 +1602,21 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct /* * Encode a LOCK request */ -static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lock_args *args) +static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { .nops = 2, }; + struct nfs_lock_opargs *opargs = args->u.lock; int status; + status = nfs_wait_on_sequence(opargs->lock_seqid, req->rq_task); + if (status != 0) + goto out; + /* Do we need to do an open_to_lock_owner? */ + if (opargs->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED) + opargs->new_lock_owner = 0; xdr_init_encode(&xdr, &req->rq_snd_buf, p); encode_compound_hdr(&xdr, &hdr); status = encode_putfh(&xdr, args->fh); @@ -1630,7 +1630,7 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lock_ /* * Encode a LOCKT request */ -static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockt_args *args) +static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1651,7 +1651,7 @@ static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lock /* * Encode a LOCKU request */ -static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_locku_args *args) +static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1985,20 +1985,14 @@ static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, uint32_t *p, const str { struct xdr_stream xdr; struct compound_hdr hdr = { - .nops = 3, + .nops = 2, }; int status; xdr_init_encode(&xdr, &req->rq_snd_buf, p); encode_compound_hdr(&xdr, &hdr); - status = encode_putfh(&xdr, args->fhandle); - if (status != 0) - goto out; - status = encode_delegreturn(&xdr, args->stateid); - if (status != 0) - goto out; - status = encode_getfattr(&xdr, args->bitmask); -out: + if ((status = encode_putfh(&xdr, args->fhandle)) == 0) + status = encode_delegreturn(&xdr, args->stateid); return status; } @@ -2961,64 +2955,55 @@ static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo) /* * We create the owner, so we know a proper owner.id length is 4. */ -static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl) +static int decode_lock_denied (struct xdr_stream *xdr, struct nfs_lock_denied *denied) { - uint64_t offset, length, clientid; uint32_t *p; - uint32_t namelen, type; + uint32_t namelen; READ_BUF(32); - READ64(offset); - READ64(length); - READ32(type); - if (fl != NULL) { - fl->fl_start = (loff_t)offset; - fl->fl_end = fl->fl_start + (loff_t)length - 1; - if (length == ~(uint64_t)0) - fl->fl_end = OFFSET_MAX; - fl->fl_type = F_WRLCK; - if (type & 1) - fl->fl_type = F_RDLCK; - fl->fl_pid = 0; - } - READ64(clientid); + READ64(denied->offset); + READ64(denied->length); + READ32(denied->type); + READ64(denied->owner.clientid); READ32(namelen); READ_BUF(namelen); + if (namelen == 4) + READ32(denied->owner.id); return -NFS4ERR_DENIED; } -static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res) +static int decode_lock(struct xdr_stream *xdr, struct nfs_lockres *res) { uint32_t *p; int status; status = decode_op_hdr(xdr, OP_LOCK); if (status == 0) { - READ_BUF(sizeof(res->stateid.data)); - COPYMEM(res->stateid.data, sizeof(res->stateid.data)); + READ_BUF(sizeof(res->u.stateid.data)); + COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data)); } else if (status == -NFS4ERR_DENIED) - return decode_lock_denied(xdr, NULL); + return decode_lock_denied(xdr, &res->u.denied); return status; } -static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res) +static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockres *res) { int status; status = decode_op_hdr(xdr, OP_LOCKT); if (status == -NFS4ERR_DENIED) - return decode_lock_denied(xdr, res->denied); + return decode_lock_denied(xdr, &res->u.denied); return status; } -static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) +static int decode_locku(struct xdr_stream *xdr, struct nfs_lockres *res) { uint32_t *p; int status; status = decode_op_hdr(xdr, OP_LOCKU); if (status == 0) { - READ_BUF(sizeof(res->stateid.data)); - COPYMEM(res->stateid.data, sizeof(res->stateid.data)); + READ_BUF(sizeof(res->u.stateid.data)); + COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data)); } return status; } @@ -3846,9 +3831,6 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, uint32_t *p, struct if (status) goto out; status = decode_open(&xdr, res); - if (status) - goto out; - decode_getfattr(&xdr, res->f_attr, res->server); out: return status; } @@ -3882,7 +3864,7 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_ /* * Decode LOCK response */ -static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lock_res *res) +static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3903,7 +3885,7 @@ static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_loc /* * Decode LOCKT response */ -static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockt_res *res) +static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -3924,7 +3906,7 @@ static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lo /* * Decode LOCKU response */ -static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_locku_res *res) +static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4192,7 +4174,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s /* * DELEGRETURN request */ -static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_delegreturnres *res) +static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *dummy) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4200,14 +4182,11 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, struct xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); status = decode_compound_hdr(&xdr, &hdr); - if (status != 0) - goto out; - status = decode_putfh(&xdr); - if (status != 0) - goto out; - status = decode_delegreturn(&xdr); - decode_getfattr(&xdr, res->fattr, res->server); -out: + if (status == 0) { + status = decode_putfh(&xdr); + if (status == 0) + status = decode_delegreturn(&xdr); + } return status; } diff --git a/trunk/fs/nfs/nfsroot.c b/trunk/fs/nfs/nfsroot.c index 985cc53b8dd5..1b272a135a31 100644 --- a/trunk/fs/nfs/nfsroot.c +++ b/trunk/fs/nfs/nfsroot.c @@ -296,8 +296,8 @@ static int __init root_nfs_name(char *name) nfs_port = -1; nfs_data.version = NFS_MOUNT_VERSION; nfs_data.flags = NFS_MOUNT_NONLM; /* No lockd in nfs root yet */ - nfs_data.rsize = NFS_DEF_FILE_IO_SIZE; - nfs_data.wsize = NFS_DEF_FILE_IO_SIZE; + nfs_data.rsize = NFS_DEF_FILE_IO_BUFFER_SIZE; + nfs_data.wsize = NFS_DEF_FILE_IO_BUFFER_SIZE; nfs_data.acregmin = 3; nfs_data.acregmax = 60; nfs_data.acdirmin = 30; diff --git a/trunk/fs/nfs/proc.c b/trunk/fs/nfs/proc.c index f5150d71c03d..e1e3ca5d746b 100644 --- a/trunk/fs/nfs/proc.c +++ b/trunk/fs/nfs/proc.c @@ -111,9 +111,6 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, }; int status; - /* Mask out the non-modebit related stuff from attr->ia_mode */ - sattr->ia_mode &= S_IALLUGO; - dprintk("NFS call setattr\n"); nfs_fattr_init(fattr); status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0); @@ -550,9 +547,10 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); -static void nfs_read_done(struct rpc_task *task, void *calldata) +static void +nfs_read_done(struct rpc_task *task) { - struct nfs_read_data *data = calldata; + struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; if (task->tk_status >= 0) { nfs_refresh_inode(data->inode, data->res.fattr); @@ -562,14 +560,9 @@ static void nfs_read_done(struct rpc_task *task, void *calldata) if (data->args.offset + data->args.count >= data->res.fattr->size) data->res.eof = 1; } - nfs_readpage_result(task, calldata); + nfs_readpage_result(task); } -static const struct rpc_call_ops nfs_read_ops = { - .rpc_call_done = nfs_read_done, - .rpc_release = nfs_readdata_release, -}; - static void nfs_proc_read_setup(struct nfs_read_data *data) { @@ -587,24 +580,20 @@ nfs_proc_read_setup(struct nfs_read_data *data) flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_read_ops, data); + rpc_init_task(task, NFS_CLIENT(inode), nfs_read_done, flags); rpc_call_setup(task, &msg, 0); } -static void nfs_write_done(struct rpc_task *task, void *calldata) +static void +nfs_write_done(struct rpc_task *task) { - struct nfs_write_data *data = calldata; + struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; if (task->tk_status >= 0) nfs_post_op_update_inode(data->inode, data->res.fattr); - nfs_writeback_done(task, calldata); + nfs_writeback_done(task); } -static const struct rpc_call_ops nfs_write_ops = { - .rpc_call_done = nfs_write_done, - .rpc_release = nfs_writedata_release, -}; - static void nfs_proc_write_setup(struct nfs_write_data *data, int how) { @@ -625,7 +614,7 @@ nfs_proc_write_setup(struct nfs_write_data *data, int how) flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; /* Finalize the task. */ - rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_write_ops, data); + rpc_init_task(task, NFS_CLIENT(inode), nfs_write_done, flags); rpc_call_setup(task, &msg, 0); } diff --git a/trunk/fs/nfs/read.c b/trunk/fs/nfs/read.c index 05eb43fadf8e..5f20eafba8ec 100644 --- a/trunk/fs/nfs/read.c +++ b/trunk/fs/nfs/read.c @@ -42,8 +42,9 @@ mempool_t *nfs_rdata_mempool; #define MIN_POOL_READ (32) -void nfs_readdata_release(void *data) +void nfs_readdata_release(struct rpc_task *task) { + struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata; nfs_readdata_free(data); } @@ -83,7 +84,7 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode, int result; struct nfs_read_data *rdata; - rdata = nfs_readdata_alloc(1); + rdata = nfs_readdata_alloc(); if (!rdata) return -ENOMEM; @@ -219,6 +220,9 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, NFS_PROTO(inode)->read_setup(data); data->task.tk_cookie = (unsigned long)inode; + data->task.tk_calldata = data; + /* Release requests */ + data->task.tk_release = nfs_readdata_release; dprintk("NFS: %4d initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n", data->task.tk_pid, @@ -283,7 +287,7 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode) nbytes = req->wb_bytes; for(;;) { - data = nfs_readdata_alloc(1); + data = nfs_readdata_alloc(); if (!data) goto out_bad; INIT_LIST_HEAD(&data->pages); @@ -339,7 +343,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode) if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) return nfs_pagein_multi(head, inode); - data = nfs_readdata_alloc(NFS_SERVER(inode)->rpages); + data = nfs_readdata_alloc(); if (!data) goto out_bad; @@ -448,9 +452,9 @@ static void nfs_readpage_result_full(struct nfs_read_data *data, int status) * This is the callback from RPC telling us whether a reply was * received or some error occurred (timeout or socket shutdown). */ -void nfs_readpage_result(struct rpc_task *task, void *calldata) +void nfs_readpage_result(struct rpc_task *task) { - struct nfs_read_data *data = calldata; + struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata; struct nfs_readargs *argp = &data->args; struct nfs_readres *resp = &data->res; int status = task->tk_status; diff --git a/trunk/fs/nfs/sysctl.c b/trunk/fs/nfs/sysctl.c deleted file mode 100644 index 4c486eb867ca..000000000000 --- a/trunk/fs/nfs/sysctl.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * linux/fs/nfs/sysctl.c - * - * Sysctl interface to NFS parameters - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "callback.h" - -static const int nfs_set_port_min = 0; -static const int nfs_set_port_max = 65535; -static struct ctl_table_header *nfs_callback_sysctl_table; -/* - * Something that isn't CTL_ANY, CTL_NONE or a value that may clash. - * Use the same values as fs/lockd/svc.c - */ -#define CTL_UNNUMBERED -2 - -static ctl_table nfs_cb_sysctls[] = { -#ifdef CONFIG_NFS_V4 - { - .ctl_name = CTL_UNNUMBERED, - .procname = "nfs_callback_tcpport", - .data = &nfs_callback_set_tcpport, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .extra1 = (int *)&nfs_set_port_min, - .extra2 = (int *)&nfs_set_port_max, - }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "idmap_cache_timeout", - .data = &nfs_idmap_cache_timeout, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies, - }, -#endif - { .ctl_name = 0 } -}; - -static ctl_table nfs_cb_sysctl_dir[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "nfs", - .mode = 0555, - .child = nfs_cb_sysctls, - }, - { .ctl_name = 0 } -}; - -static ctl_table nfs_cb_sysctl_root[] = { - { - .ctl_name = CTL_FS, - .procname = "fs", - .mode = 0555, - .child = nfs_cb_sysctl_dir, - }, - { .ctl_name = 0 } -}; - -int nfs_register_sysctl(void) -{ - nfs_callback_sysctl_table = register_sysctl_table(nfs_cb_sysctl_root, 0); - if (nfs_callback_sysctl_table == NULL) - return -ENOMEM; - return 0; -} - -void nfs_unregister_sysctl(void) -{ - unregister_sysctl_table(nfs_callback_sysctl_table); - nfs_callback_sysctl_table = NULL; -} diff --git a/trunk/fs/nfs/unlink.c b/trunk/fs/nfs/unlink.c index a65c7b53d558..d639d172d568 100644 --- a/trunk/fs/nfs/unlink.c +++ b/trunk/fs/nfs/unlink.c @@ -87,9 +87,10 @@ nfs_copy_dname(struct dentry *dentry, struct nfs_unlinkdata *data) * We delay initializing RPC info until after the call to dentry_iput() * in order to minimize races against rename(). */ -static void nfs_async_unlink_init(struct rpc_task *task, void *calldata) +static void +nfs_async_unlink_init(struct rpc_task *task) { - struct nfs_unlinkdata *data = calldata; + struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata; struct dentry *dir = data->dir; struct rpc_message msg = { .rpc_cred = data->cred, @@ -115,9 +116,10 @@ static void nfs_async_unlink_init(struct rpc_task *task, void *calldata) * * Do the directory attribute update. */ -static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) +static void +nfs_async_unlink_done(struct rpc_task *task) { - struct nfs_unlinkdata *data = calldata; + struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata; struct dentry *dir = data->dir; struct inode *dir_i; @@ -139,18 +141,13 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata) * We need to call nfs_put_unlinkdata as a 'tk_release' task since the * rpc_task would be freed too. */ -static void nfs_async_unlink_release(void *calldata) +static void +nfs_async_unlink_release(struct rpc_task *task) { - struct nfs_unlinkdata *data = calldata; + struct nfs_unlinkdata *data = (struct nfs_unlinkdata *)task->tk_calldata; nfs_put_unlinkdata(data); } -static const struct rpc_call_ops nfs_unlink_ops = { - .rpc_call_prepare = nfs_async_unlink_init, - .rpc_call_done = nfs_async_unlink_done, - .rpc_release = nfs_async_unlink_release, -}; - /** * nfs_async_unlink - asynchronous unlinking of a file * @dentry: dentry to unlink @@ -160,6 +157,7 @@ nfs_async_unlink(struct dentry *dentry) { struct dentry *dir = dentry->d_parent; struct nfs_unlinkdata *data; + struct rpc_task *task; struct rpc_clnt *clnt = NFS_CLIENT(dir->d_inode); int status = -ENOMEM; @@ -180,13 +178,17 @@ nfs_async_unlink(struct dentry *dentry) nfs_deletes = data; data->count = 1; - rpc_init_task(&data->task, clnt, RPC_TASK_ASYNC, &nfs_unlink_ops, data); + task = &data->task; + rpc_init_task(task, clnt, nfs_async_unlink_done , RPC_TASK_ASYNC); + task->tk_calldata = data; + task->tk_action = nfs_async_unlink_init; + task->tk_release = nfs_async_unlink_release; spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_NFSFS_RENAMED; spin_unlock(&dentry->d_lock); - rpc_sleep_on(&nfs_delete_queue, &data->task, NULL, NULL); + rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL); status = 0; out: return status; diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index 9449b6835509..3107908e5f3f 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -89,38 +89,24 @@ static mempool_t *nfs_commit_mempool; static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion); -static inline struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount) +static inline struct nfs_write_data *nfs_commit_alloc(void) { struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS); - if (p) { memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->pages); - if (pagecount < NFS_PAGEVEC_SIZE) - p->pagevec = &p->page_array[0]; - else { - size_t size = ++pagecount * sizeof(struct page *); - p->pagevec = kmalloc(size, GFP_NOFS); - if (p->pagevec) { - memset(p->pagevec, 0, size); - } else { - mempool_free(p, nfs_commit_mempool); - p = NULL; - } - } } return p; } static inline void nfs_commit_free(struct nfs_write_data *p) { - if (p && (p->pagevec != &p->page_array[0])) - kfree(p->pagevec); mempool_free(p, nfs_commit_mempool); } -void nfs_writedata_release(void *wdata) +static void nfs_writedata_release(struct rpc_task *task) { + struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata; nfs_writedata_free(wdata); } @@ -182,7 +168,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode, int result, written = 0; struct nfs_write_data *wdata; - wdata = nfs_writedata_alloc(1); + wdata = nfs_writedata_alloc(); if (!wdata) return -ENOMEM; @@ -246,16 +232,19 @@ static int nfs_writepage_async(struct nfs_open_context *ctx, unsigned int offset, unsigned int count) { struct nfs_page *req; + int status; req = nfs_update_request(ctx, inode, page, offset, count); - if (IS_ERR(req)) - return PTR_ERR(req); + status = (IS_ERR(req)) ? PTR_ERR(req) : 0; + if (status < 0) + goto out; /* Update file length */ nfs_grow_file(page, offset, count); /* Set the PG_uptodate flag? */ nfs_mark_uptodate(page, offset, count); nfs_unlock_request(req); - return 0; + out: + return status; } static int wb_priority(struct writeback_control *wbc) @@ -315,8 +304,11 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) lock_kernel(); if (!IS_SYNC(inode) && inode_referenced) { err = nfs_writepage_async(ctx, inode, page, 0, offset); - if (!wbc->for_writepages) - nfs_flush_inode(inode, 0, 0, wb_priority(wbc)); + if (err >= 0) { + err = 0; + if (wbc->for_reclaim) + nfs_flush_inode(inode, 0, 0, FLUSH_STABLE); + } } else { err = nfs_writepage_sync(ctx, inode, page, 0, offset, priority); @@ -885,6 +877,9 @@ static void nfs_write_rpcsetup(struct nfs_page *req, data->task.tk_priority = flush_task_priority(how); data->task.tk_cookie = (unsigned long)inode; + data->task.tk_calldata = data; + /* Release requests */ + data->task.tk_release = nfs_writedata_release; dprintk("NFS: %4d initiated write call (req %s/%Ld, %u bytes @ offset %Lu)\n", data->task.tk_pid, @@ -924,7 +919,7 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how) nbytes = req->wb_bytes; for (;;) { - data = nfs_writedata_alloc(1); + data = nfs_writedata_alloc(); if (!data) goto out_bad; list_add(&data->pages, &list); @@ -988,7 +983,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how) if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE) return nfs_flush_multi(head, inode, how); - data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages); + data = nfs_writedata_alloc(); if (!data) goto out_bad; @@ -1142,9 +1137,9 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status) /* * This function is called when the WRITE call is complete. */ -void nfs_writeback_done(struct rpc_task *task, void *calldata) +void nfs_writeback_done(struct rpc_task *task) { - struct nfs_write_data *data = calldata; + struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; struct nfs_writeargs *argp = &data->args; struct nfs_writeres *resp = &data->res; @@ -1211,8 +1206,9 @@ void nfs_writeback_done(struct rpc_task *task, void *calldata) #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) -void nfs_commit_release(void *wdata) +static void nfs_commit_release(struct rpc_task *task) { + struct nfs_write_data *wdata = (struct nfs_write_data *)task->tk_calldata; nfs_commit_free(wdata); } @@ -1248,6 +1244,9 @@ static void nfs_commit_rpcsetup(struct list_head *head, data->task.tk_priority = flush_task_priority(how); data->task.tk_cookie = (unsigned long)inode; + data->task.tk_calldata = data; + /* Release requests */ + data->task.tk_release = nfs_commit_release; dprintk("NFS: %4d initiated commit call\n", data->task.tk_pid); } @@ -1256,12 +1255,12 @@ static void nfs_commit_rpcsetup(struct list_head *head, * Commit dirty pages */ static int -nfs_commit_list(struct inode *inode, struct list_head *head, int how) +nfs_commit_list(struct list_head *head, int how) { struct nfs_write_data *data; struct nfs_page *req; - data = nfs_commit_alloc(NFS_SERVER(inode)->wpages); + data = nfs_commit_alloc(); if (!data) goto out_bad; @@ -1284,9 +1283,10 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) /* * COMMIT call returned */ -void nfs_commit_done(struct rpc_task *task, void *calldata) +void +nfs_commit_done(struct rpc_task *task) { - struct nfs_write_data *data = calldata; + struct nfs_write_data *data = (struct nfs_write_data *)task->tk_calldata; struct nfs_page *req; int res = 0; @@ -1366,7 +1366,7 @@ int nfs_commit_inode(struct inode *inode, int how) res = nfs_scan_commit(inode, &head, 0, 0); spin_unlock(&nfsi->req_lock); if (res) { - error = nfs_commit_list(inode, &head, how); + error = nfs_commit_list(&head, how); if (error < 0) return error; } @@ -1377,23 +1377,22 @@ int nfs_commit_inode(struct inode *inode, int how) int nfs_sync_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how) { - int nocommit = how & FLUSH_NOCOMMIT; - int wait = how & FLUSH_WAIT; - int error; + int error, + wait; - how &= ~(FLUSH_WAIT|FLUSH_NOCOMMIT); + wait = how & FLUSH_WAIT; + how &= ~FLUSH_WAIT; do { - if (wait) { + error = 0; + if (wait) error = nfs_wait_on_requests(inode, idx_start, npages); - if (error != 0) - continue; - } - error = nfs_flush_inode(inode, idx_start, npages, how); - if (error != 0) - continue; - if (!nocommit) + if (error == 0) + error = nfs_flush_inode(inode, idx_start, npages, how); +#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) + if (error == 0) error = nfs_commit_inode(inode, how); +#endif } while (error > 0); return error; } diff --git a/trunk/fs/nfsd/nfs3proc.c b/trunk/fs/nfsd/nfs3proc.c index 6d2dfed1de08..041380fe667b 100644 --- a/trunk/fs/nfsd/nfs3proc.c +++ b/trunk/fs/nfsd/nfs3proc.c @@ -56,20 +56,13 @@ static int nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, struct nfsd3_attrstat *resp) { - int err, nfserr; + int nfserr; dprintk("nfsd: GETATTR(3) %s\n", - SVCFH_fmt(&argp->fh)); + SVCFH_fmt(&argp->fh)); fh_copy(&resp->fh, &argp->fh); nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP); - if (nfserr) - RETURN_STATUS(nfserr); - - err = vfs_getattr(resp->fh.fh_export->ex_mnt, - resp->fh.fh_dentry, &resp->stat); - nfserr = nfserrno(err); - RETURN_STATUS(nfserr); } diff --git a/trunk/fs/nfsd/nfs3xdr.c b/trunk/fs/nfsd/nfs3xdr.c index 243d94b9653a..9147b8524d05 100644 --- a/trunk/fs/nfsd/nfs3xdr.c +++ b/trunk/fs/nfsd/nfs3xdr.c @@ -154,34 +154,37 @@ decode_sattr3(u32 *p, struct iattr *iap) } static inline u32 * -encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, - struct kstat *stat) +encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) { + struct vfsmount *mnt = fhp->fh_export->ex_mnt; struct dentry *dentry = fhp->fh_dentry; + struct kstat stat; struct timespec time; - *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); - *p++ = htonl((u32) stat->mode); - *p++ = htonl((u32) stat->nlink); - *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid)); - *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid)); - if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) { + vfs_getattr(mnt, dentry, &stat); + + *p++ = htonl(nfs3_ftypes[(stat.mode & S_IFMT) >> 12]); + *p++ = htonl((u32) stat.mode); + *p++ = htonl((u32) stat.nlink); + *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid)); + *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid)); + if (S_ISLNK(stat.mode) && stat.size > NFS3_MAXPATHLEN) { p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); } else { - p = xdr_encode_hyper(p, (u64) stat->size); + p = xdr_encode_hyper(p, (u64) stat.size); } - p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9); - *p++ = htonl((u32) MAJOR(stat->rdev)); - *p++ = htonl((u32) MINOR(stat->rdev)); + p = xdr_encode_hyper(p, ((u64)stat.blocks) << 9); + *p++ = htonl((u32) MAJOR(stat.rdev)); + *p++ = htonl((u32) MINOR(stat.rdev)); if (is_fsid(fhp, rqstp->rq_reffh)) p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid); else - p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat->dev)); - p = xdr_encode_hyper(p, (u64) stat->ino); - p = encode_time3(p, &stat->atime); + p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat.dev)); + p = xdr_encode_hyper(p, (u64) stat.ino); + p = encode_time3(p, &stat.atime); lease_get_mtime(dentry->d_inode, &time); p = encode_time3(p, &time); - p = encode_time3(p, &stat->ctime); + p = encode_time3(p, &stat.ctime); return p; } @@ -229,14 +232,8 @@ encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) { struct dentry *dentry = fhp->fh_dentry; if (dentry && dentry->d_inode != NULL) { - int err; - struct kstat stat; - - err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat); - if (!err) { - *p++ = xdr_one; /* attributes follow */ - return encode_fattr3(rqstp, p, fhp, &stat); - } + *p++ = xdr_one; /* attributes follow */ + return encode_fattr3(rqstp, p, fhp); } *p++ = xdr_zero; return p; @@ -619,7 +616,7 @@ nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p, struct nfsd3_attrstat *resp) { if (resp->status == 0) - p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat); + p = encode_fattr3(rqstp, p, &resp->fh); return xdr_ressize_check(rqstp, p); } diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index d828662d737d..583c0710e45e 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -53,7 +53,7 @@ #define NFSPROC4_CB_COMPOUND 1 /* declarations */ -static const struct rpc_call_ops nfs4_cb_null_ops; +static void nfs4_cb_null(struct rpc_task *task); /* Index of predefined Linux callback client operations */ @@ -431,6 +431,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) } clnt->cl_intr = 0; clnt->cl_softrtry = 1; + clnt->cl_chatty = 1; /* Kick rpciod, put the call on the wire. */ @@ -446,7 +447,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) msg.rpc_cred = nfsd4_lookupcred(clp,0); if (IS_ERR(msg.rpc_cred)) goto out_rpciod; - status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); + status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, nfs4_cb_null, NULL); put_rpccred(msg.rpc_cred); if (status != 0) { @@ -468,7 +469,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) } static void -nfs4_cb_null(struct rpc_task *task, void *dummy) +nfs4_cb_null(struct rpc_task *task) { struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; struct nfs4_callback *cb = &clp->cl_callback; @@ -487,10 +488,6 @@ nfs4_cb_null(struct rpc_task *task, void *dummy) put_nfs4_client(clp); } -static const struct rpc_call_ops nfs4_cb_null_ops = { - .rpc_call_done = nfs4_cb_null, -}; - /* * called with dp->dl_count inc'ed. * nfs4_lock_state() may or may not have been called. diff --git a/trunk/fs/nfsd/nfsxdr.c b/trunk/fs/nfsd/nfsxdr.c index aa7bb41b293d..b45999ff33e6 100644 --- a/trunk/fs/nfsd/nfsxdr.c +++ b/trunk/fs/nfsd/nfsxdr.c @@ -152,44 +152,46 @@ decode_sattr(u32 *p, struct iattr *iap) } static inline u32 * -encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, - struct kstat *stat) +encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) { + struct vfsmount *mnt = fhp->fh_export->ex_mnt; struct dentry *dentry = fhp->fh_dentry; + struct kstat stat; int type; struct timespec time; - type = (stat->mode & S_IFMT); + vfs_getattr(mnt, dentry, &stat); + type = (stat.mode & S_IFMT); *p++ = htonl(nfs_ftypes[type >> 12]); - *p++ = htonl((u32) stat->mode); - *p++ = htonl((u32) stat->nlink); - *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid)); - *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid)); + *p++ = htonl((u32) stat.mode); + *p++ = htonl((u32) stat.nlink); + *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid)); + *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid)); - if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) { + if (S_ISLNK(type) && stat.size > NFS_MAXPATHLEN) { *p++ = htonl(NFS_MAXPATHLEN); } else { - *p++ = htonl((u32) stat->size); + *p++ = htonl((u32) stat.size); } - *p++ = htonl((u32) stat->blksize); + *p++ = htonl((u32) stat.blksize); if (S_ISCHR(type) || S_ISBLK(type)) - *p++ = htonl(new_encode_dev(stat->rdev)); + *p++ = htonl(new_encode_dev(stat.rdev)); else *p++ = htonl(0xffffffff); - *p++ = htonl((u32) stat->blocks); + *p++ = htonl((u32) stat.blocks); if (is_fsid(fhp, rqstp->rq_reffh)) *p++ = htonl((u32) fhp->fh_export->ex_fsid); else - *p++ = htonl(new_encode_dev(stat->dev)); - *p++ = htonl((u32) stat->ino); - *p++ = htonl((u32) stat->atime.tv_sec); - *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0); + *p++ = htonl(new_encode_dev(stat.dev)); + *p++ = htonl((u32) stat.ino); + *p++ = htonl((u32) stat.atime.tv_sec); + *p++ = htonl(stat.atime.tv_nsec ? stat.atime.tv_nsec / 1000 : 0); lease_get_mtime(dentry->d_inode, &time); *p++ = htonl((u32) time.tv_sec); *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0); - *p++ = htonl((u32) stat->ctime.tv_sec); - *p++ = htonl(stat->ctime.tv_nsec ? stat->ctime.tv_nsec / 1000 : 0); + *p++ = htonl((u32) stat.ctime.tv_sec); + *p++ = htonl(stat.ctime.tv_nsec ? stat.ctime.tv_nsec / 1000 : 0); return p; } @@ -197,9 +199,7 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp, /* Helper function for NFSv2 ACL code */ u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp) { - struct kstat stat; - vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, &stat); - return encode_fattr(rqstp, p, fhp, &stat); + return encode_fattr(rqstp, p, fhp); } /* @@ -394,7 +394,7 @@ int nfssvc_encode_attrstat(struct svc_rqst *rqstp, u32 *p, struct nfsd_attrstat *resp) { - p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); + p = encode_fattr(rqstp, p, &resp->fh); return xdr_ressize_check(rqstp, p); } @@ -403,7 +403,7 @@ nfssvc_encode_diropres(struct svc_rqst *rqstp, u32 *p, struct nfsd_diropres *resp) { p = encode_fh(p, &resp->fh); - p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); + p = encode_fattr(rqstp, p, &resp->fh); return xdr_ressize_check(rqstp, p); } @@ -428,7 +428,7 @@ int nfssvc_encode_readres(struct svc_rqst *rqstp, u32 *p, struct nfsd_readres *resp) { - p = encode_fattr(rqstp, p, &resp->fh, &resp->stat); + p = encode_fattr(rqstp, p, &resp->fh); *p++ = htonl(resp->count); xdr_ressize_check(rqstp, p); diff --git a/trunk/fs/nfsd/vfs.c b/trunk/fs/nfsd/vfs.c index df4019f04560..af7c3c3074b0 100644 --- a/trunk/fs/nfsd/vfs.c +++ b/trunk/fs/nfsd/vfs.c @@ -717,33 +717,27 @@ nfsd_close(struct file *filp) * As this calls fsync (not fdatasync) there is no need for a write_inode * after it. */ -static inline int nfsd_dosync(struct file *filp, struct dentry *dp, - struct file_operations *fop) +static inline void nfsd_dosync(struct file *filp, struct dentry *dp, + struct file_operations *fop) { struct inode *inode = dp->d_inode; int (*fsync) (struct file *, struct dentry *, int); - int err = nfs_ok; filemap_fdatawrite(inode->i_mapping); if (fop && (fsync = fop->fsync)) - err=fsync(filp, dp, 0); + fsync(filp, dp, 0); filemap_fdatawait(inode->i_mapping); - - return nfserrno(err); } -static int +static void nfsd_sync(struct file *filp) { - int err; struct inode *inode = filp->f_dentry->d_inode; dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name); down(&inode->i_sem); - err=nfsd_dosync(filp, filp->f_dentry, filp->f_op); + nfsd_dosync(filp, filp->f_dentry, filp->f_op); up(&inode->i_sem); - - return err; } void @@ -880,16 +874,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, return err; } -static void kill_suid(struct dentry *dentry) -{ - struct iattr ia; - ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID; - - down(&dentry->d_inode->i_sem); - notify_change(dentry, &ia); - up(&dentry->d_inode->i_sem); -} - static inline int nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, loff_t offset, struct kvec *vec, int vlen, @@ -943,8 +927,14 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, } /* clear setuid/setgid flag after write */ - if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) - kill_suid(dentry); + if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) { + struct iattr ia; + ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID; + + down(&inode->i_sem); + notify_change(dentry, &ia); + up(&inode->i_sem); + } if (err >= 0 && stable) { static ino_t last_ino; @@ -972,7 +962,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, if (inode->i_state & I_DIRTY) { dprintk("nfsd: write sync %d\n", current->pid); - err=nfsd_sync(file); + nfsd_sync(file); } #if 0 wake_up(&inode->i_wait); @@ -1076,7 +1066,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, return err; if (EX_ISSYNC(fhp->fh_export)) { if (file->f_op && file->f_op->fsync) { - err = nfsd_sync(file); + nfsd_sync(file); } else { err = nfserr_notsupp; } diff --git a/trunk/fs/partitions/Kconfig b/trunk/fs/partitions/Kconfig index e227a04261ab..656bc43431b9 100644 --- a/trunk/fs/partitions/Kconfig +++ b/trunk/fs/partitions/Kconfig @@ -85,7 +85,7 @@ config ATARI_PARTITION config IBM_PARTITION bool "IBM disk label and partition support" - depends on PARTITION_ADVANCED && S390 + depends on PARTITION_ADVANCED && ARCH_S390 help Say Y here if you would like to be able to read the hard disk partition table format used by IBM DASD disks operating under CMS. diff --git a/trunk/fs/partitions/ibm.c b/trunk/fs/partitions/ibm.c index 78010ad60e47..6327bcb2d73d 100644 --- a/trunk/fs/partitions/ibm.c +++ b/trunk/fs/partitions/ibm.c @@ -56,10 +56,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) struct hd_geometry *geo; char type[5] = {0,}; char name[7] = {0,}; - union label_t { - struct vtoc_volume_label vol; - struct vtoc_cms_label cms; - } *label; + struct vtoc_volume_label *vlabel; unsigned char *data; Sector sect; @@ -67,8 +64,9 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) goto out_noinfo; if ((geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL)) == NULL) goto out_nogeo; - if ((label = kmalloc(sizeof(union label_t), GFP_KERNEL)) == NULL) - goto out_nolab; + if ((vlabel = kmalloc(sizeof(struct vtoc_volume_label), + GFP_KERNEL)) == NULL) + goto out_novlab; if (ioctl_by_bdev(bdev, BIODASDINFO, (unsigned long)info) != 0 || ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0) @@ -89,7 +87,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) strncpy(name, data + 8, 6); else strncpy(name, data + 4, 6); - memcpy(label, data, sizeof(union label_t)); + memcpy (vlabel, data, sizeof(struct vtoc_volume_label)); put_dev_sector(sect); EBCASC(type, 4); @@ -102,12 +100,14 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) /* * VM style CMS1 labeled disk */ - if (label->cms.disk_offset != 0) { + int *label = (int *) vlabel; + + if (label[13] != 0) { printk("CMS1/%8s(MDSK):", name); /* disk is reserved minidisk */ - blocksize = label->cms.block_size; - offset = label->cms.disk_offset; - size = (label->cms.block_count - 1) * (blocksize >> 9); + blocksize = label[3]; + offset = label[13]; + size = (label[7] - 1)*(blocksize >> 9); } else { printk("CMS1/%8s:", name); offset = (info->label_block + 1); @@ -126,7 +126,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) printk("VOL1/%8s:", name); /* get block number and read then go through format1 labels */ - blk = cchhb2blk(&label->vol.vtoc, geo) + 1; + blk = cchhb2blk(&vlabel->vtoc, geo) + 1; counter = 0; while ((data = read_dev_sector(bdev, blk*(blocksize/512), §)) != NULL) { @@ -174,7 +174,7 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) } printk("\n"); - kfree(label); + kfree(vlabel); kfree(geo); kfree(info); return 1; @@ -182,8 +182,8 @@ ibm_partition(struct parsed_partitions *state, struct block_device *bdev) out_readerr: out_badsect: out_noioctl: - kfree(label); -out_nolab: + kfree(vlabel); +out_novlab: kfree(geo); out_nogeo: kfree(info); diff --git a/trunk/fs/proc/array.c b/trunk/fs/proc/array.c index 5e9251f65317..3e1239e4b303 100644 --- a/trunk/fs/proc/array.c +++ b/trunk/fs/proc/array.c @@ -308,7 +308,7 @@ int proc_pid_status(struct task_struct *task, char * buffer) buffer = task_sig(task, buffer); buffer = task_cap(task, buffer); buffer = cpuset_task_status_allowed(task, buffer); -#if defined(CONFIG_S390) +#if defined(CONFIG_ARCH_S390) buffer = task_show_regs(task, buffer); #endif return buffer - orig; diff --git a/trunk/fs/ramfs/Makefile b/trunk/fs/ramfs/Makefile index 5a0236e02ee1..f096f3007091 100644 --- a/trunk/fs/ramfs/Makefile +++ b/trunk/fs/ramfs/Makefile @@ -4,6 +4,4 @@ obj-$(CONFIG_RAMFS) += ramfs.o -file-mmu-y := file-nommu.o -file-mmu-$(CONFIG_MMU) := file-mmu.o -ramfs-objs += inode.o $(file-mmu-y) +ramfs-objs := inode.o diff --git a/trunk/fs/ramfs/file-mmu.c b/trunk/fs/ramfs/file-mmu.c deleted file mode 100644 index 2115383dcc8d..000000000000 --- a/trunk/fs/ramfs/file-mmu.c +++ /dev/null @@ -1,57 +0,0 @@ -/* file-mmu.c: ramfs MMU-based file operations - * - * Resizable simple ram filesystem for Linux. - * - * Copyright (C) 2000 Linus Torvalds. - * 2000 Transmeta Corp. - * - * Usage limits added by David Gibson, Linuxcare Australia. - * This file is released under the GPL. - */ - -/* - * NOTE! This filesystem is probably most useful - * not as a real filesystem, but as an example of - * how virtual filesystems can be written. - * - * It doesn't get much simpler than this. Consider - * that this file implements the full semantics of - * a POSIX-compliant read-write filesystem. - * - * Note in particular how the filesystem does not - * need to implement any data structures of its own - * to keep track of the virtual data: using the VFS - * caches is sufficient. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "internal.h" - -struct address_space_operations ramfs_aops = { - .readpage = simple_readpage, - .prepare_write = simple_prepare_write, - .commit_write = simple_commit_write -}; - -struct file_operations ramfs_file_operations = { - .read = generic_file_read, - .write = generic_file_write, - .mmap = generic_file_mmap, - .fsync = simple_sync_file, - .sendfile = generic_file_sendfile, - .llseek = generic_file_llseek, -}; - -struct inode_operations ramfs_file_inode_operations = { - .getattr = simple_getattr, -}; diff --git a/trunk/fs/ramfs/file-nommu.c b/trunk/fs/ramfs/file-nommu.c deleted file mode 100644 index 3f810acd0bfa..000000000000 --- a/trunk/fs/ramfs/file-nommu.c +++ /dev/null @@ -1,292 +0,0 @@ -/* file-nommu.c: no-MMU version of ramfs - * - * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "internal.h" - -static int ramfs_nommu_setattr(struct dentry *, struct iattr *); - -struct address_space_operations ramfs_aops = { - .readpage = simple_readpage, - .prepare_write = simple_prepare_write, - .commit_write = simple_commit_write -}; - -struct file_operations ramfs_file_operations = { - .mmap = ramfs_nommu_mmap, - .get_unmapped_area = ramfs_nommu_get_unmapped_area, - .read = generic_file_read, - .write = generic_file_write, - .fsync = simple_sync_file, - .sendfile = generic_file_sendfile, - .llseek = generic_file_llseek, -}; - -struct inode_operations ramfs_file_inode_operations = { - .setattr = ramfs_nommu_setattr, - .getattr = simple_getattr, -}; - -/*****************************************************************************/ -/* - * add a contiguous set of pages into a ramfs inode when it's truncated from - * size 0 on the assumption that it's going to be used for an mmap of shared - * memory - */ -static int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) -{ - struct pagevec lru_pvec; - unsigned long npages, xpages, loop, limit; - struct page *pages; - unsigned order; - void *data; - int ret; - - /* make various checks */ - order = get_order(newsize); - if (unlikely(order >= MAX_ORDER)) - goto too_big; - - limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit != RLIM_INFINITY && newsize > limit) - goto fsize_exceeded; - - if (newsize > inode->i_sb->s_maxbytes) - goto too_big; - - i_size_write(inode, newsize); - - /* allocate enough contiguous pages to be able to satisfy the - * request */ - pages = alloc_pages(mapping_gfp_mask(inode->i_mapping), order); - if (!pages) - return -ENOMEM; - - /* split the high-order page into an array of single pages */ - xpages = 1UL << order; - npages = (newsize + PAGE_SIZE - 1) >> PAGE_SHIFT; - - for (loop = 0; loop < npages; loop++) - set_page_count(pages + loop, 1); - - /* trim off any pages we don't actually require */ - for (loop = npages; loop < xpages; loop++) - __free_page(pages + loop); - - /* clear the memory we allocated */ - newsize = PAGE_SIZE * npages; - data = page_address(pages); - memset(data, 0, newsize); - - /* attach all the pages to the inode's address space */ - pagevec_init(&lru_pvec, 0); - for (loop = 0; loop < npages; loop++) { - struct page *page = pages + loop; - - ret = add_to_page_cache(page, inode->i_mapping, loop, GFP_KERNEL); - if (ret < 0) - goto add_error; - - if (!pagevec_add(&lru_pvec, page)) - __pagevec_lru_add(&lru_pvec); - - unlock_page(page); - } - - pagevec_lru_add(&lru_pvec); - return 0; - - fsize_exceeded: - send_sig(SIGXFSZ, current, 0); - too_big: - return -EFBIG; - - add_error: - page_cache_release(pages + loop); - for (loop++; loop < npages; loop++) - __free_page(pages + loop); - return ret; -} - -/*****************************************************************************/ -/* - * check that file shrinkage doesn't leave any VMAs dangling in midair - */ -static int ramfs_nommu_check_mappings(struct inode *inode, - size_t newsize, size_t size) -{ - struct vm_area_struct *vma; - struct prio_tree_iter iter; - - /* search for VMAs that fall within the dead zone */ - vma_prio_tree_foreach(vma, &iter, &inode->i_mapping->i_mmap, - newsize >> PAGE_SHIFT, - (size + PAGE_SIZE - 1) >> PAGE_SHIFT - ) { - /* found one - only interested if it's shared out of the page - * cache */ - if (vma->vm_flags & VM_SHARED) - return -ETXTBSY; /* not quite true, but near enough */ - } - - return 0; -} - -/*****************************************************************************/ -/* - * - */ -static int ramfs_nommu_resize(struct inode *inode, loff_t newsize, loff_t size) -{ - int ret; - - /* assume a truncate from zero size is going to be for the purposes of - * shared mmap */ - if (size == 0) { - if (unlikely(newsize >> 32)) - return -EFBIG; - - return ramfs_nommu_expand_for_mapping(inode, newsize); - } - - /* check that a decrease in size doesn't cut off any shared mappings */ - if (newsize < size) { - ret = ramfs_nommu_check_mappings(inode, newsize, size); - if (ret < 0) - return ret; - } - - ret = vmtruncate(inode, size); - - return ret; -} - -/*****************************************************************************/ -/* - * handle a change of attributes - * - we're specifically interested in a change of size - */ -static int ramfs_nommu_setattr(struct dentry *dentry, struct iattr *ia) -{ - struct inode *inode = dentry->d_inode; - unsigned int old_ia_valid = ia->ia_valid; - int ret = 0; - - /* by providing our own setattr() method, we skip this quotaism */ - if ((old_ia_valid & ATTR_UID && ia->ia_uid != inode->i_uid) || - (old_ia_valid & ATTR_GID && ia->ia_gid != inode->i_gid)) - ret = DQUOT_TRANSFER(inode, ia) ? -EDQUOT : 0; - - /* pick out size-changing events */ - if (ia->ia_valid & ATTR_SIZE) { - loff_t size = i_size_read(inode); - if (ia->ia_size != size) { - ret = ramfs_nommu_resize(inode, ia->ia_size, size); - if (ret < 0 || ia->ia_valid == ATTR_SIZE) - goto out; - } else { - /* we skipped the truncate but must still update - * timestamps - */ - ia->ia_valid |= ATTR_MTIME|ATTR_CTIME; - } - } - - ret = inode_setattr(inode, ia); - out: - ia->ia_valid = old_ia_valid; - return ret; -} - -/*****************************************************************************/ -/* - * try to determine where a shared mapping can be made - * - we require that: - * - the pages to be mapped must exist - * - the pages be physically contiguous in sequence - */ -unsigned long ramfs_nommu_get_unmapped_area(struct file *file, - unsigned long addr, unsigned long len, - unsigned long pgoff, unsigned long flags) -{ - unsigned long maxpages, lpages, nr, loop, ret; - struct inode *inode = file->f_dentry->d_inode; - struct page **pages = NULL, **ptr, *page; - loff_t isize; - - if (!(flags & MAP_SHARED)) - return addr; - - /* the mapping mustn't extend beyond the EOF */ - lpages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; - isize = i_size_read(inode); - - ret = -EINVAL; - maxpages = (isize + PAGE_SIZE - 1) >> PAGE_SHIFT; - if (pgoff >= maxpages) - goto out; - - if (maxpages - pgoff < lpages) - goto out; - - /* gang-find the pages */ - ret = -ENOMEM; - pages = kzalloc(lpages * sizeof(struct page *), GFP_KERNEL); - if (!pages) - goto out; - - nr = find_get_pages(inode->i_mapping, pgoff, lpages, pages); - if (nr != lpages) - goto out; /* leave if some pages were missing */ - - /* check the pages for physical adjacency */ - ptr = pages; - page = *ptr++; - page++; - for (loop = lpages; loop > 1; loop--) - if (*ptr++ != page++) - goto out; - - /* okay - all conditions fulfilled */ - ret = (unsigned long) page_address(pages[0]); - - out: - if (pages) { - ptr = pages; - for (loop = lpages; loop > 0; loop--) - put_page(*ptr++); - kfree(pages); - } - - return ret; -} - -/*****************************************************************************/ -/* - * set up a mapping - */ -int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma) -{ - return 0; -} diff --git a/trunk/fs/ramfs/inode.c b/trunk/fs/ramfs/inode.c index c66bd5e4c05c..0a88917605ae 100644 --- a/trunk/fs/ramfs/inode.c +++ b/trunk/fs/ramfs/inode.c @@ -34,12 +34,13 @@ #include #include -#include "internal.h" /* some random number */ #define RAMFS_MAGIC 0x858458f6 static struct super_operations ramfs_ops; +static struct address_space_operations ramfs_aops; +static struct inode_operations ramfs_file_inode_operations; static struct inode_operations ramfs_dir_inode_operations; static struct backing_dev_info ramfs_backing_dev_info = { @@ -141,6 +142,25 @@ static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * return error; } +static struct address_space_operations ramfs_aops = { + .readpage = simple_readpage, + .prepare_write = simple_prepare_write, + .commit_write = simple_commit_write +}; + +struct file_operations ramfs_file_operations = { + .read = generic_file_read, + .write = generic_file_write, + .mmap = generic_file_mmap, + .fsync = simple_sync_file, + .sendfile = generic_file_sendfile, + .llseek = generic_file_llseek, +}; + +static struct inode_operations ramfs_file_inode_operations = { + .getattr = simple_getattr, +}; + static struct inode_operations ramfs_dir_inode_operations = { .create = ramfs_create, .lookup = simple_lookup, diff --git a/trunk/fs/ramfs/internal.h b/trunk/fs/ramfs/internal.h deleted file mode 100644 index 272c8a7120b0..000000000000 --- a/trunk/fs/ramfs/internal.h +++ /dev/null @@ -1,15 +0,0 @@ -/* internal.h: ramfs internal definitions - * - * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * 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. - */ - - -extern struct address_space_operations ramfs_aops; -extern struct file_operations ramfs_file_operations; -extern struct inode_operations ramfs_file_inode_operations; diff --git a/trunk/fs/ufs/dir.c b/trunk/fs/ufs/dir.c index 7c10c68902ae..d0915fba155a 100644 --- a/trunk/fs/ufs/dir.c +++ b/trunk/fs/ufs/dir.c @@ -491,7 +491,7 @@ int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir, UFSD(("ino %u, reclen %u, namlen %u, name %s\n", fs32_to_cpu(sb, de->d_ino), - fs16_to_cpu(sb, de->d_reclen), + fs16to_cpu(sb, de->d_reclen), ufs_get_de_namlen(sb, de), de->d_name)) while (i < bh->b_size) { diff --git a/trunk/include/asm-alpha/atomic.h b/trunk/include/asm-alpha/atomic.h index cb03bbe92cdf..6183eab006d4 100644 --- a/trunk/include/asm-alpha/atomic.h +++ b/trunk/include/asm-alpha/atomic.h @@ -216,5 +216,4 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) #define smp_mb__before_atomic_inc() smp_mb() #define smp_mb__after_atomic_inc() smp_mb() -#include #endif /* _ALPHA_ATOMIC_H */ diff --git a/trunk/include/asm-alpha/dma-mapping.h b/trunk/include/asm-alpha/dma-mapping.h index 9dc7256cf979..680f7ecbb28f 100644 --- a/trunk/include/asm-alpha/dma-mapping.h +++ b/trunk/include/asm-alpha/dma-mapping.h @@ -16,7 +16,7 @@ #define dma_free_coherent(dev, size, va, addr) \ pci_free_consistent(alpha_gendev_to_pci(dev), size, va, addr) #define dma_map_page(dev, page, off, size, dir) \ - pci_map_page(alpha_gendev_to_pci(dev), page, off, size, dir) + pci_map_single(alpha_gendev_to_pci(dev), page, off, size, dir) #define dma_unmap_page(dev, addr, size, dir) \ pci_unmap_page(alpha_gendev_to_pci(dev), addr, size, dir) #define dma_map_sg(dev, sg, nents, dir) \ diff --git a/trunk/include/asm-alpha/hardirq.h b/trunk/include/asm-alpha/hardirq.h index 7bb6a36c96a1..c0593f9b21e1 100644 --- a/trunk/include/asm-alpha/hardirq.h +++ b/trunk/include/asm-alpha/hardirq.h @@ -13,8 +13,6 @@ typedef struct { #include /* Standard mappings for irq_cpustat_t above */ -void ack_bad_irq(unsigned int irq); - #define HARDIRQ_BITS 12 /* diff --git a/trunk/include/asm-alpha/mman.h b/trunk/include/asm-alpha/mman.h index f6439532a262..eb9c279045ef 100644 --- a/trunk/include/asm-alpha/mman.h +++ b/trunk/include/asm-alpha/mman.h @@ -42,7 +42,6 @@ #define MADV_WILLNEED 3 /* will need these pages */ #define MADV_SPACEAVAIL 5 /* ensure resources are available */ #define MADV_DONTNEED 6 /* don't need these pages */ -#define MADV_REMOVE 7 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-arm/atomic.h b/trunk/include/asm-arm/atomic.h index f72b63309bc5..d586f65c8228 100644 --- a/trunk/include/asm-arm/atomic.h +++ b/trunk/include/asm-arm/atomic.h @@ -205,6 +205,5 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif #endif diff --git a/trunk/include/asm-arm/mman.h b/trunk/include/asm-arm/mman.h index f0bebca2ac21..8e4f69c4fa5f 100644 --- a/trunk/include/asm-arm/mman.h +++ b/trunk/include/asm-arm/mman.h @@ -35,7 +35,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-arm26/atomic.h b/trunk/include/asm-arm26/atomic.h index 3074b0e76343..a47cadc59686 100644 --- a/trunk/include/asm-arm26/atomic.h +++ b/trunk/include/asm-arm26/atomic.h @@ -118,6 +118,5 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif #endif diff --git a/trunk/include/asm-arm26/mman.h b/trunk/include/asm-arm26/mman.h index 0ed7780541fa..cc27b8240265 100644 --- a/trunk/include/asm-arm26/mman.h +++ b/trunk/include/asm-arm26/mman.h @@ -35,7 +35,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-cris/atomic.h b/trunk/include/asm-cris/atomic.h index 2df2c7aa19b7..683b05a57d88 100644 --- a/trunk/include/asm-cris/atomic.h +++ b/trunk/include/asm-cris/atomic.h @@ -156,5 +156,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif diff --git a/trunk/include/asm-cris/mman.h b/trunk/include/asm-cris/mman.h index 5a382b8bf3f7..8570e72b9502 100644 --- a/trunk/include/asm-cris/mman.h +++ b/trunk/include/asm-cris/mman.h @@ -37,7 +37,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-frv/atomic.h b/trunk/include/asm-frv/atomic.h index 3f54fea2b051..f6539ff569c5 100644 --- a/trunk/include/asm-frv/atomic.h +++ b/trunk/include/asm-frv/atomic.h @@ -426,5 +426,4 @@ extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new); }) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) -#include #endif /* _ASM_ATOMIC_H */ diff --git a/trunk/include/asm-frv/futex.h b/trunk/include/asm-frv/futex.h index fca9d90e32c9..9feff4ce1424 100644 --- a/trunk/include/asm-frv/futex.h +++ b/trunk/include/asm-frv/futex.h @@ -7,7 +7,47 @@ #include #include -extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr); +static inline int +futex_atomic_op_inuser (int encoded_op, int __user *uaddr) +{ + int op = (encoded_op >> 28) & 7; + int cmp = (encoded_op >> 24) & 15; + int oparg = (encoded_op << 8) >> 20; + int cmparg = (encoded_op << 20) >> 20; + int oldval = 0, ret; + if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) + oparg = 1 << oparg; + + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) + return -EFAULT; + + inc_preempt_count(); + + switch (op) { + case FUTEX_OP_SET: + case FUTEX_OP_ADD: + case FUTEX_OP_OR: + case FUTEX_OP_ANDN: + case FUTEX_OP_XOR: + default: + ret = -ENOSYS; + } + + dec_preempt_count(); + + if (!ret) { + switch (cmp) { + case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; + case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; + case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; + case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; + case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; + case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; + default: ret = -ENOSYS; + } + } + return ret; +} #endif #endif diff --git a/trunk/include/asm-frv/mman.h b/trunk/include/asm-frv/mman.h index 8af4a41c255e..c684720dfbdd 100644 --- a/trunk/include/asm-frv/mman.h +++ b/trunk/include/asm-frv/mman.h @@ -35,7 +35,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-frv/signal.h b/trunk/include/asm-frv/signal.h index 67366894780f..d407bde57eca 100644 --- a/trunk/include/asm-frv/signal.h +++ b/trunk/include/asm-frv/signal.h @@ -151,6 +151,7 @@ typedef struct sigaltstack { size_t ss_size; } stack_t; +extern int do_signal(struct pt_regs *regs, sigset_t *oldset); #define ptrace_signal_deliver(regs, cookie) do { } while (0) #ifdef __KERNEL__ diff --git a/trunk/include/asm-generic/atomic.h b/trunk/include/asm-generic/atomic.h deleted file mode 100644 index e0a28b925ef0..000000000000 --- a/trunk/include/asm-generic/atomic.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef _ASM_GENERIC_ATOMIC_H -#define _ASM_GENERIC_ATOMIC_H -/* - * Copyright (C) 2005 Silicon Graphics, Inc. - * Christoph Lameter - * - * Allows to provide arch independent atomic definitions without the need to - * edit all arch specific atomic.h files. - */ - - -/* - * Suppport for atomic_long_t - * - * Casts for parameters are avoided for existing atomic functions in order to - * avoid issues with cast-as-lval under gcc 4.x and other limitations that the - * macros of a platform may have. - */ - -#if BITS_PER_LONG == 64 - -typedef atomic64_t atomic_long_t; - -#define ATOMIC_LONG_INIT(i) ATOMIC64_INIT(i) - -static inline long atomic_long_read(atomic_long_t *l) -{ - atomic64_t *v = (atomic64_t *)l; - - return (long)atomic64_read(v); -} - -static inline void atomic_long_set(atomic_long_t *l, long i) -{ - atomic64_t *v = (atomic64_t *)l; - - atomic_set(v, i); -} - -static inline void atomic_long_inc(atomic_long_t *l) -{ - atomic64_t *v = (atomic64_t *)l; - - atomic64_inc(v); -} - -static inline void atomic_long_dec(atomic_long_t *l) -{ - atomic64_t *v = (atomic64_t *)l; - - atomic64_dec(v); -} - -static inline void atomic_long_add(long i, atomic_long_t *l) -{ - atomic64_t *v = (atomic64_t *)l; - - atomic64_add(i, v); -} - -static inline void atomic_long_sub(long i, atomic_long_t *l) -{ - atomic64_t *v = (atomic64_t *)l; - - atomic64_sub(i, v); -} - -#else - -typedef atomic_t atomic_long_t; - -#define ATOMIC_LONG_INIT(i) ATOMIC_INIT(i) -static inline long atomic_long_read(atomic_long_t *l) -{ - atomic_t *v = (atomic_t *)l; - - return (long)atomic_read(v); -} - -static inline void atomic_long_set(atomic_long_t *l, long i) -{ - atomic_t *v = (atomic_t *)l; - - atomic_set(v, i); -} - -static inline void atomic_long_inc(atomic_long_t *l) -{ - atomic_t *v = (atomic_t *)l; - - atomic_inc(v); -} - -static inline void atomic_long_dec(atomic_long_t *l) -{ - atomic_t *v = (atomic_t *)l; - - atomic_dec(v); -} - -static inline void atomic_long_add(long i, atomic_long_t *l) -{ - atomic_t *v = (atomic_t *)l; - - atomic_add(i, v); -} - -static inline void atomic_long_sub(long i, atomic_long_t *l) -{ - atomic_t *v = (atomic_t *)l; - - atomic_sub(i, v); -} - -#endif -#endif diff --git a/trunk/include/asm-generic/vmlinux.lds.h b/trunk/include/asm-generic/vmlinux.lds.h index 35de20cf8fac..094d4917c1a9 100644 --- a/trunk/include/asm-generic/vmlinux.lds.h +++ b/trunk/include/asm-generic/vmlinux.lds.h @@ -10,8 +10,6 @@ #define ALIGN_FUNCTION() . = ALIGN(8) #define RODATA \ - . = ALIGN(4096); \ - __start_rodata = .; \ .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \ *(.rodata) *(.rodata.*) \ *(__vermagic) /* Kernel version magic */ \ @@ -76,8 +74,6 @@ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ *(__ksymtab_strings) \ } \ - __end_rodata = .; \ - . = ALIGN(4096); \ \ /* Built-in module parameters. */ \ __param : AT(ADDR(__param) - LOAD_OFFSET) { \ diff --git a/trunk/include/asm-h8300/atomic.h b/trunk/include/asm-h8300/atomic.h index d891541e89c3..f23d86819ea8 100644 --- a/trunk/include/asm-h8300/atomic.h +++ b/trunk/include/asm-h8300/atomic.h @@ -137,5 +137,4 @@ static __inline__ void atomic_set_mask(unsigned long mask, unsigned long *v) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif /* __ARCH_H8300_ATOMIC __ */ diff --git a/trunk/include/asm-h8300/irq.h b/trunk/include/asm-h8300/irq.h index 73065f5bda0e..5027181ed067 100644 --- a/trunk/include/asm-h8300/irq.h +++ b/trunk/include/asm-h8300/irq.h @@ -61,6 +61,11 @@ static __inline__ int irq_canonicalize(int irq) extern void enable_irq(unsigned int); extern void disable_irq(unsigned int); + +/* + * Some drivers want these entry points + */ +#define enable_irq_nosync(x) enable_irq(x) #define disable_irq_nosync(x) disable_irq(x) struct irqaction; diff --git a/trunk/include/asm-h8300/mman.h b/trunk/include/asm-h8300/mman.h index 744a8fb485c2..63f727a59850 100644 --- a/trunk/include/asm-h8300/mman.h +++ b/trunk/include/asm-h8300/mman.h @@ -35,7 +35,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-i386/atomic.h b/trunk/include/asm-i386/atomic.h index 7a5472d77091..c68557aa04b2 100644 --- a/trunk/include/asm-i386/atomic.h +++ b/trunk/include/asm-i386/atomic.h @@ -254,5 +254,4 @@ __asm__ __volatile__(LOCK "orl %0,%1" \ #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif diff --git a/trunk/include/asm-i386/bitops.h b/trunk/include/asm-i386/bitops.h index 65679aca4b22..4807aa1d2e3d 100644 --- a/trunk/include/asm-i386/bitops.h +++ b/trunk/include/asm-i386/bitops.h @@ -332,9 +332,9 @@ static inline unsigned long __ffs(unsigned long word) * Returns the bit-number of the first set bit, not the number of the byte * containing a bit. */ -static inline unsigned find_first_bit(const unsigned long *addr, unsigned size) +static inline int find_first_bit(const unsigned long *addr, unsigned size) { - unsigned x = 0; + int x = 0; while (x < size) { unsigned long val = *addr++; @@ -367,6 +367,11 @@ static inline unsigned long ffz(unsigned long word) return word; } +/* + * fls: find last bit set. + */ + +#define fls(x) generic_fls(x) #define fls64(x) generic_fls64(x) #ifdef __KERNEL__ @@ -409,23 +414,6 @@ static inline int ffs(int x) return r+1; } -/** - * fls - find last bit set - * @x: the word to search - * - * This is defined the same way as ffs. - */ -static inline int fls(int x) -{ - int r; - - __asm__("bsrl %1,%0\n\t" - "jnz 1f\n\t" - "movl $-1,%0\n" - "1:" : "=r" (r) : "rm" (x)); - return r+1; -} - /** * hweightN - returns the hamming weight of a N-bit word * @x: the word to weigh diff --git a/trunk/include/asm-i386/bugs.h b/trunk/include/asm-i386/bugs.h index 50233e0345fb..ea54540638d2 100644 --- a/trunk/include/asm-i386/bugs.h +++ b/trunk/include/asm-i386/bugs.h @@ -8,6 +8,9 @@ * * - Channing Corn (tests & fixes), * - Andrew D. Balsa (code cleanup). + * + * Pentium III FXSR, SSE support + * Gareth Hughes , May 2000 */ /* @@ -73,7 +76,25 @@ static void __init check_fpu(void) return; } -/* trap_init() enabled FXSR and company _before_ testing for FP problems here. */ +/* Enable FXSR and company _before_ testing for FP problems. */ + /* + * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned. + */ + if (offsetof(struct task_struct, thread.i387.fxsave) & 15) { + extern void __buggy_fxsr_alignment(void); + __buggy_fxsr_alignment(); + } + if (cpu_has_fxsr) { + printk(KERN_INFO "Enabling fast FPU save and restore... "); + set_in_cr4(X86_CR4_OSFXSR); + printk("done.\n"); + } + if (cpu_has_xmm) { + printk(KERN_INFO "Enabling unmasked SIMD FPU exception support... "); + set_in_cr4(X86_CR4_OSXMMEXCPT); + printk("done.\n"); + } + /* Test for the divl bug.. */ __asm__("fninit\n\t" "fldl %1\n\t" diff --git a/trunk/include/asm-i386/cacheflush.h b/trunk/include/asm-i386/cacheflush.h index 7199f7b326f1..2ea36dea37d9 100644 --- a/trunk/include/asm-i386/cacheflush.h +++ b/trunk/include/asm-i386/cacheflush.h @@ -31,8 +31,4 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot); void kernel_map_pages(struct page *page, int numpages, int enable); #endif -#ifdef CONFIG_DEBUG_RODATA -void mark_rodata_ro(void); -#endif - #endif /* _I386_CACHEFLUSH_H */ diff --git a/trunk/include/asm-i386/desc.h b/trunk/include/asm-i386/desc.h index 494e73bca095..29b851a18c6e 100644 --- a/trunk/include/asm-i386/desc.h +++ b/trunk/include/asm-i386/desc.h @@ -15,6 +15,9 @@ #include extern struct desc_struct cpu_gdt_table[GDT_ENTRIES]; +DECLARE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]); + +#define get_cpu_gdt_table(_cpu) (per_cpu(cpu_gdt_table,_cpu)) DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); @@ -26,11 +29,6 @@ struct Xgt_desc_struct { extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS]; -static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu) -{ - return ((struct desc_struct *)cpu_gdt_descr[cpu].address); -} - #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8)) #define load_LDT_desc() __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8)) diff --git a/trunk/include/asm-i386/mach-bigsmp/mach_apic.h b/trunk/include/asm-i386/mach-bigsmp/mach_apic.h index 18b19a773440..ba936d4daedb 100644 --- a/trunk/include/asm-i386/mach-bigsmp/mach_apic.h +++ b/trunk/include/asm-i386/mach-bigsmp/mach_apic.h @@ -1,10 +1,17 @@ #ifndef __ASM_MACH_APIC_H #define __ASM_MACH_APIC_H - - -extern u8 bios_cpu_apicid[]; - -#define xapic_phys_to_log_apicid(cpu) (bios_cpu_apicid[cpu]) +#include + +#define SEQUENTIAL_APICID +#ifdef SEQUENTIAL_APICID +#define xapic_phys_to_log_apicid(phys_apic) ( (1ul << ((phys_apic) & 0x3)) |\ + ((phys_apic<<2) & (~0xf)) ) +#elif CLUSTERED_APICID +#define xapic_phys_to_log_apicid(phys_apic) ( (1ul << ((phys_apic) & 0x3)) |\ + ((phys_apic) & (~0xf)) ) +#endif + +#define NO_BALANCE_IRQ (1) #define esr_disable (1) static inline int apic_id_registered(void) @@ -12,6 +19,7 @@ static inline int apic_id_registered(void) return (1); } +#define APIC_DFR_VALUE (APIC_DFR_CLUSTER) /* Round robin the irqs amoung the online cpus */ static inline cpumask_t target_cpus(void) { @@ -24,34 +32,29 @@ static inline cpumask_t target_cpus(void) } while (cpu >= NR_CPUS); return cpumask_of_cpu(cpu); } +#define TARGET_CPUS (target_cpus()) -#undef APIC_DEST_LOGICAL -#define APIC_DEST_LOGICAL 0 -#define TARGET_CPUS (target_cpus()) -#define APIC_DFR_VALUE (APIC_DFR_FLAT) -#define INT_DELIVERY_MODE (dest_Fixed) -#define INT_DEST_MODE (0) /* phys delivery to target proc */ -#define NO_BALANCE_IRQ (0) -#define WAKE_SECONDARY_VIA_INIT - +#define INT_DELIVERY_MODE dest_Fixed +#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid) { - return (0); + return 0; } -static inline unsigned long check_apicid_present(int bit) +/* we don't use the phys_cpu_present_map to indicate apicid presence */ +static inline unsigned long check_apicid_present(int bit) { - return (1); + return 1; } -static inline unsigned long calculate_ldr(int cpu) +#define apicid_cluster(apicid) (apicid & 0xF0) + +static inline unsigned long calculate_ldr(unsigned long old) { - unsigned long val, id; - val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; - id = xapic_phys_to_log_apicid(cpu); - val |= SET_APIC_LOGICAL_ID(id); - return val; + unsigned long id; + id = xapic_phys_to_log_apicid(hard_smp_processor_id()); + return ((old & ~APIC_LDR_MASK) | SET_APIC_LOGICAL_ID(id)); } /* @@ -64,35 +67,37 @@ static inline unsigned long calculate_ldr(int cpu) static inline void init_apic_ldr(void) { unsigned long val; - int cpu = smp_processor_id(); apic_write_around(APIC_DFR, APIC_DFR_VALUE); - val = calculate_ldr(cpu); + val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; + val = calculate_ldr(val); apic_write_around(APIC_LDR, val); } static inline void clustered_apic_check(void) { printk("Enabling APIC mode: %s. Using %d I/O APICs\n", - "Physflat", nr_ioapics); + "Cluster", nr_ioapics); } static inline int multi_timer_check(int apic, int irq) { - return (0); + return 0; } static inline int apicid_to_node(int logical_apicid) { - return (0); + return 0; } +extern u8 bios_cpu_apicid[]; + static inline int cpu_present_to_apicid(int mps_cpu) { if (mps_cpu < NR_CPUS) - return (int) bios_cpu_apicid[mps_cpu]; - - return BAD_APICID; + return (int)bios_cpu_apicid[mps_cpu]; + else + return BAD_APICID; } static inline physid_mask_t apicid_to_cpu_present(int phys_apicid) @@ -104,10 +109,10 @@ extern u8 cpu_2_logical_apicid[]; /* Mapping from cpu number to logical apicid */ static inline int cpu_to_logical_apicid(int cpu) { - if (cpu >= NR_CPUS) - return BAD_APICID; - return cpu_physical_id(cpu); -} + if (cpu >= NR_CPUS) + return BAD_APICID; + return (int)cpu_2_logical_apicid[cpu]; + } static inline int mpc_apic_id(struct mpc_config_processor *m, struct mpc_config_translation *translation_record) @@ -123,9 +128,11 @@ static inline int mpc_apic_id(struct mpc_config_processor *m, static inline physid_mask_t ioapic_phys_id_map(physid_mask_t phys_map) { /* For clustered we don't have a good way to do this yet - hack */ - return physids_promote(0xFFL); + return physids_promote(0xFUL); } +#define WAKE_SECONDARY_VIA_INIT + static inline void setup_portio_remap(void) { } diff --git a/trunk/include/asm-i386/mach-bigsmp/mach_apicdef.h b/trunk/include/asm-i386/mach-bigsmp/mach_apicdef.h index a58ab5a75c8c..23e58b317c79 100644 --- a/trunk/include/asm-i386/mach-bigsmp/mach_apicdef.h +++ b/trunk/include/asm-i386/mach-bigsmp/mach_apicdef.h @@ -1,11 +1,11 @@ #ifndef __ASM_MACH_APICDEF_H #define __ASM_MACH_APICDEF_H -#define APIC_ID_MASK (0xFF<<24) +#define APIC_ID_MASK (0x0F<<24) static inline unsigned get_apic_id(unsigned long x) { - return (((x)>>24)&0xFF); + return (((x)>>24)&0x0F); } #define GET_APIC_ID(x) get_apic_id(x) diff --git a/trunk/include/asm-i386/mman.h b/trunk/include/asm-i386/mman.h index ba4941e6f643..196619a83854 100644 --- a/trunk/include/asm-i386/mman.h +++ b/trunk/include/asm-i386/mman.h @@ -35,7 +35,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-i386/mmzone.h b/trunk/include/asm-i386/mmzone.h index 74f595d80579..620a90641ea8 100644 --- a/trunk/include/asm-i386/mmzone.h +++ b/trunk/include/asm-i386/mmzone.h @@ -76,6 +76,11 @@ static inline int pfn_to_nid(unsigned long pfn) * Following are macros that each numa implmentation must define. */ +/* + * Given a kernel address, find the home node of the underlying memory. + */ +#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT) + #define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn) #define node_end_pfn(nid) \ ({ \ diff --git a/trunk/include/asm-i386/module.h b/trunk/include/asm-i386/module.h index 424661d25bd3..eb7f2b4234aa 100644 --- a/trunk/include/asm-i386/module.h +++ b/trunk/include/asm-i386/module.h @@ -52,10 +52,8 @@ struct mod_arch_specific #define MODULE_PROC_FAMILY "CYRIXIII " #elif defined CONFIG_MVIAC3_2 #define MODULE_PROC_FAMILY "VIAC3-2 " -#elif defined CONFIG_MGEODEGX1 +#elif CONFIG_MGEODEGX1 #define MODULE_PROC_FAMILY "GEODEGX1 " -#elif defined CONFIG_MGEODE_LX -#define MODULE_PROC_FAMILY "GEODE " #else #error unknown processor family #endif diff --git a/trunk/include/asm-i386/mpspec_def.h b/trunk/include/asm-i386/mpspec_def.h index 76feedf85a8a..a961093dbf88 100644 --- a/trunk/include/asm-i386/mpspec_def.h +++ b/trunk/include/asm-i386/mpspec_def.h @@ -75,7 +75,7 @@ struct mpc_config_bus { unsigned char mpc_type; unsigned char mpc_busid; - unsigned char mpc_bustype[6]; + unsigned char mpc_bustype[6] __attribute((packed)); }; /* List of Bus Type string values, Intel MP Spec. */ diff --git a/trunk/include/asm-i386/segment.h b/trunk/include/asm-i386/segment.h index faf995307b9e..bb5ff5b2c02e 100644 --- a/trunk/include/asm-i386/segment.h +++ b/trunk/include/asm-i386/segment.h @@ -91,20 +91,6 @@ #define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1) #define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8) -/* The PnP BIOS entries in the GDT */ -#define GDT_ENTRY_PNPBIOS_CS32 (GDT_ENTRY_PNPBIOS_BASE + 0) -#define GDT_ENTRY_PNPBIOS_CS16 (GDT_ENTRY_PNPBIOS_BASE + 1) -#define GDT_ENTRY_PNPBIOS_DS (GDT_ENTRY_PNPBIOS_BASE + 2) -#define GDT_ENTRY_PNPBIOS_TS1 (GDT_ENTRY_PNPBIOS_BASE + 3) -#define GDT_ENTRY_PNPBIOS_TS2 (GDT_ENTRY_PNPBIOS_BASE + 4) - -/* The PnP BIOS selectors */ -#define PNP_CS32 (GDT_ENTRY_PNPBIOS_CS32 * 8) /* segment for calling fn */ -#define PNP_CS16 (GDT_ENTRY_PNPBIOS_CS16 * 8) /* code segment for BIOS */ -#define PNP_DS (GDT_ENTRY_PNPBIOS_DS * 8) /* data segment for BIOS */ -#define PNP_TS1 (GDT_ENTRY_PNPBIOS_TS1 * 8) /* transfer data segment */ -#define PNP_TS2 (GDT_ENTRY_PNPBIOS_TS2 * 8) /* another data segment */ - /* * The interrupt descriptor table has room for 256 idt's, * the global descriptor table is dependent on the number diff --git a/trunk/include/asm-i386/system.h b/trunk/include/asm-i386/system.h index 9c0593b7a94e..772f85da1206 100644 --- a/trunk/include/asm-i386/system.h +++ b/trunk/include/asm-i386/system.h @@ -54,7 +54,23 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \ ); } while(0) #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) ) -#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1) ) +#define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1)>>12 ) + +static inline unsigned long _get_base(char * addr) +{ + unsigned long __base; + __asm__("movb %3,%%dh\n\t" + "movb %2,%%dl\n\t" + "shll $16,%%edx\n\t" + "movw %1,%%dx" + :"=&d" (__base) + :"m" (*((addr)+2)), + "m" (*((addr)+4)), + "m" (*((addr)+7))); + return __base; +} + +#define get_base(ldt) _get_base( ((char *)&(ldt)) ) /* * Load a segment. Fall back on loading the zero @@ -124,19 +140,6 @@ __asm__ __volatile__ ("movw %%dx,%1\n\t" \ :"=r" (__dummy)); \ __dummy; \ }) - -#define read_cr4_safe() ({ \ - unsigned int __dummy; \ - /* This could fault if %cr4 does not exist */ \ - __asm__("1: movl %%cr4, %0 \n" \ - "2: \n" \ - ".section __ex_table,\"a\" \n" \ - ".long 1b,2b \n" \ - ".previous \n" \ - : "=r" (__dummy): "0" (0)); \ - __dummy; \ -}) - #define write_cr4(x) \ __asm__ __volatile__("movl %0,%%cr4": :"r" (x)); #define stts() write_cr0(8 | read_cr0()) diff --git a/trunk/include/asm-i386/unistd.h b/trunk/include/asm-i386/unistd.h index fe38b9a96233..0f92e78dfea1 100644 --- a/trunk/include/asm-i386/unistd.h +++ b/trunk/include/asm-i386/unistd.h @@ -256,7 +256,7 @@ #define __NR_io_submit 248 #define __NR_io_cancel 249 #define __NR_fadvise64 250 -/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */ +#define __NR_set_zone_reclaim 251 #define __NR_exit_group 252 #define __NR_lookup_dcookie 253 #define __NR_epoll_create 254 diff --git a/trunk/include/asm-ia64/atomic.h b/trunk/include/asm-ia64/atomic.h index 15cf7984c48e..2fbebf85c31d 100644 --- a/trunk/include/asm-ia64/atomic.h +++ b/trunk/include/asm-ia64/atomic.h @@ -192,5 +192,4 @@ atomic64_add_negative (__s64 i, atomic64_t *v) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif /* _ASM_IA64_ATOMIC_H */ diff --git a/trunk/include/asm-ia64/mman.h b/trunk/include/asm-ia64/mman.h index 828beb24a20e..1c0a73af1461 100644 --- a/trunk/include/asm-ia64/mman.h +++ b/trunk/include/asm-ia64/mman.h @@ -43,7 +43,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-ia64/unistd.h b/trunk/include/asm-ia64/unistd.h index 2bf543493cb8..6d96a67439be 100644 --- a/trunk/include/asm-ia64/unistd.h +++ b/trunk/include/asm-ia64/unistd.h @@ -265,7 +265,7 @@ #define __NR_keyctl 1273 #define __NR_ioprio_set 1274 #define __NR_ioprio_get 1275 -/* 1276 is available for reuse (was briefly sys_set_zone_reclaim) */ +#define __NR_set_zone_reclaim 1276 #define __NR_inotify_init 1277 #define __NR_inotify_add_watch 1278 #define __NR_inotify_rm_watch 1279 diff --git a/trunk/include/asm-m32r/assembler.h b/trunk/include/asm-m32r/assembler.h index b7f4d8aaeb46..e1dff9d6baad 100644 --- a/trunk/include/asm-m32r/assembler.h +++ b/trunk/include/asm-m32r/assembler.h @@ -52,7 +52,7 @@ or3 \reg, \reg, #low(\x) .endm -#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104)) +#if !defined(CONFIG_CHIP_M32102) #define STI(reg) STI_M reg .macro STI_M reg setpsw #0x40 -> nop @@ -64,7 +64,7 @@ clrpsw #0x40 -> nop ; WORKAROUND: "-> nop" is a workaround for the M32700(TS1). .endm -#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ +#else /* CONFIG_CHIP_M32102 */ #define STI(reg) STI_M reg .macro STI_M reg mvfc \reg, psw @@ -191,12 +191,12 @@ and \reg, sp .endm -#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104)) +#if !defined(CONFIG_CHIP_M32102) .macro SWITCH_TO_KERNEL_STACK ; switch to kernel stack (spi) clrpsw #0x80 -> nop .endm -#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ +#else /* CONFIG_CHIP_M32102 */ .macro SWITCH_TO_KERNEL_STACK push r0 ; save r0 for working mvfc r0, psw @@ -218,7 +218,7 @@ .fillinsn 2: .endm -#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ +#endif /* CONFIG_CHIP_M32102 */ #endif /* __ASSEMBLY__ */ diff --git a/trunk/include/asm-m32r/atomic.h b/trunk/include/asm-m32r/atomic.h index 70761278b6cb..ef1fb8ea4726 100644 --- a/trunk/include/asm-m32r/atomic.h +++ b/trunk/include/asm-m32r/atomic.h @@ -313,5 +313,4 @@ static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *addr) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif /* _ASM_M32R_ATOMIC_H */ diff --git a/trunk/include/asm-m32r/cacheflush.h b/trunk/include/asm-m32r/cacheflush.h index e57427b6e249..46fc4c325108 100644 --- a/trunk/include/asm-m32r/cacheflush.h +++ b/trunk/include/asm-m32r/cacheflush.h @@ -7,7 +7,7 @@ extern void _flush_cache_all(void); extern void _flush_cache_copyback_all(void); -#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) +#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_OPSP) #define flush_cache_all() do { } while (0) #define flush_cache_mm(mm) do { } while (0) #define flush_cache_range(vma, start, end) do { } while (0) diff --git a/trunk/include/asm-m32r/irq.h b/trunk/include/asm-m32r/irq.h index ca943954572a..8ed77968ecb4 100644 --- a/trunk/include/asm-m32r/irq.h +++ b/trunk/include/asm-m32r/irq.h @@ -65,22 +65,6 @@ #define NR_IRQS \ (OPSPUT_NUM_CPU_IRQ + OPSPUT_NUM_PLD_IRQ \ + OPSPUT_NUM_LCD_PLD_IRQ + OPSPUT_NUM_LAN_PLD_IRQ) - -#elif defined(CONFIG_PLAT_M32104UT) -/* - * IRQ definitions for M32104UT - * M32104 Chip: 64 interrupts - * ICU of M32104UT-on-board PLD: 32 interrupts cascaded to INT1# chip pin - */ -#define M32104UT_NUM_CPU_IRQ (64) -#define M32104UT_NUM_PLD_IRQ (32) -#define M32104UT_IRQ_BASE 0 -#define M32104UT_CPU_IRQ_BASE M32104UT_IRQ_BASE -#define M32104UT_PLD_IRQ_BASE (M32104UT_CPU_IRQ_BASE + M32104UT_NUM_CPU_IRQ) - -#define NR_IRQS \ - (M32104UT_NUM_CPU_IRQ + M32104UT_NUM_PLD_IRQ) - #else #define NR_IRQS 64 #endif diff --git a/trunk/include/asm-m32r/m32102.h b/trunk/include/asm-m32r/m32102.h index a1f0d1fe9eb8..cb98101f4f6e 100644 --- a/trunk/include/asm-m32r/m32102.h +++ b/trunk/include/asm-m32r/m32102.h @@ -11,11 +11,7 @@ /*======================================================================* * Special Function Register *======================================================================*/ -#if !defined(CONFIG_CHIP_M32104) #define M32R_SFR_OFFSET (0x00E00000) /* 0x00E00000-0x00EFFFFF 1[MB] */ -#else -#define M32R_SFR_OFFSET (0x00700000) /* 0x00700000-0x007FFFFF 1[MB] */ -#endif /* * Clock and Power Management registers. @@ -104,7 +100,7 @@ #define M32R_MFT5RLD_PORTL (0x0C+M32R_MFT5_OFFSET) /* MFT4 reload */ #define M32R_MFT5CMPRLD_PORTL (0x10+M32R_MFT5_OFFSET) /* MFT4 compare reload */ -#if defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32104) +#ifdef CONFIG_CHIP_M32700 #define M32R_MFTCR_MFT0MSK (1UL<<31) /* b0 */ #define M32R_MFTCR_MFT1MSK (1UL<<30) /* b1 */ #define M32R_MFTCR_MFT2MSK (1UL<<29) /* b2 */ @@ -117,7 +113,7 @@ #define M32R_MFTCR_MFT3EN (1UL<<20) /* b11 */ #define M32R_MFTCR_MFT4EN (1UL<<19) /* b12 */ #define M32R_MFTCR_MFT5EN (1UL<<18) /* b13 */ -#else /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */ +#else /* not CONFIG_CHIP_M32700 */ #define M32R_MFTCR_MFT0MSK (1UL<<15) /* b16 */ #define M32R_MFTCR_MFT1MSK (1UL<<14) /* b17 */ #define M32R_MFTCR_MFT2MSK (1UL<<13) /* b18 */ @@ -130,7 +126,7 @@ #define M32R_MFTCR_MFT3EN (1UL<<4) /* b27 */ #define M32R_MFTCR_MFT4EN (1UL<<3) /* b28 */ #define M32R_MFTCR_MFT5EN (1UL<<2) /* b29 */ -#endif /* not CONFIG_CHIP_M32700 && not CONFIG_CHIP_M32104 */ +#endif /* not CONFIG_CHIP_M32700 */ #define M32R_MFTMOD_CC_MASK (1UL<<15) /* b16 */ #define M32R_MFTMOD_TCCR (1UL<<13) /* b18 */ @@ -245,24 +241,8 @@ #define M32R_IRQ_MFT1 (17) /* MFT1 */ #define M32R_IRQ_MFT2 (18) /* MFT2 */ #define M32R_IRQ_MFT3 (19) /* MFT3 */ -#ifdef CONFIG_CHIP_M32104 -#define M32R_IRQ_MFTX0 (24) /* MFTX0 */ -#define M32R_IRQ_MFTX1 (25) /* MFTX1 */ -#define M32R_IRQ_DMA0 (32) /* DMA0 */ -#define M32R_IRQ_DMA1 (33) /* DMA1 */ -#define M32R_IRQ_DMA2 (34) /* DMA2 */ -#define M32R_IRQ_DMA3 (35) /* DMA3 */ -#define M32R_IRQ_SIO0_R (40) /* SIO0 send */ -#define M32R_IRQ_SIO0_S (41) /* SIO0 receive */ -#define M32R_IRQ_SIO1_R (42) /* SIO1 send */ -#define M32R_IRQ_SIO1_S (43) /* SIO1 receive */ -#define M32R_IRQ_SIO2_R (44) /* SIO2 send */ -#define M32R_IRQ_SIO2_S (45) /* SIO2 receive */ -#define M32R_IRQ_SIO3_R (46) /* SIO3 send */ -#define M32R_IRQ_SIO3_S (47) /* SIO3 receive */ -#define M32R_IRQ_ADC (56) /* ADC */ -#define M32R_IRQ_PC (57) /* PC */ -#else /* ! M32104 */ +#define M32R_IRQ_MFT4 (20) /* MFT4 */ +#define M32R_IRQ_MFT5 (21) /* MFT5 */ #define M32R_IRQ_DMA0 (32) /* DMA0 */ #define M32R_IRQ_DMA1 (33) /* DMA1 */ #define M32R_IRQ_SIO0_R (48) /* SIO0 send */ @@ -275,7 +255,6 @@ #define M32R_IRQ_SIO3_S (55) /* SIO3 receive */ #define M32R_IRQ_SIO4_R (56) /* SIO4 send */ #define M32R_IRQ_SIO4_S (57) /* SIO4 receive */ -#endif /* ! M32104 */ #ifdef CONFIG_SMP #define M32R_IRQ_IPI0 (56) @@ -302,12 +281,15 @@ #define M32R_FPGA_VERSION0_PORTL (0x30+M32R_FPGA_TOP) #define M32R_FPGA_VERSION1_PORTL (0x34+M32R_FPGA_TOP) -#endif /* CONFIG_SMP */ - #ifndef __ASSEMBLY__ +/* For NETDEV WATCHDOG */ typedef struct { unsigned long icucr; /* ICU Control Register */ } icu_data_t; + +extern icu_data_t icu_data[]; #endif +#endif /* CONFIG_SMP */ + #endif /* _M32102_H_ */ diff --git a/trunk/include/asm-m32r/m32104ut/m32104ut_pld.h b/trunk/include/asm-m32r/m32104ut/m32104ut_pld.h deleted file mode 100644 index a4eac20553df..000000000000 --- a/trunk/include/asm-m32r/m32104ut/m32104ut_pld.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * include/asm/m32104ut/m32104ut_pld.h - * - * Definitions for Programable Logic Device(PLD) on M32104UT board. - * Based on m32700ut_pld.h - * - * Copyright (c) 2002 Takeo Takahashi - * Copyright (c) 2005 Naoto Sugai - * - * 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 archive for more details. - */ - -#ifndef _M32104UT_M32104UT_PLD_H -#define _M32104UT_M32104UT_PLD_H - -#include - -#if defined(CONFIG_PLAT_M32104UT) -#define PLD_PLAT_BASE 0x02c00000 -#else -#error "no platform configuration" -#endif - -#ifndef __ASSEMBLY__ -/* - * C functions use non-cache address. - */ -#define PLD_BASE (PLD_PLAT_BASE /* + NONCACHE_OFFSET */) -#define __reg8 (volatile unsigned char *) -#define __reg16 (volatile unsigned short *) -#define __reg32 (volatile unsigned int *) -#else -#define PLD_BASE (PLD_PLAT_BASE + NONCACHE_OFFSET) -#define __reg8 -#define __reg16 -#define __reg32 -#endif /* __ASSEMBLY__ */ - -/* CFC */ -#define PLD_CFRSTCR __reg16(PLD_BASE + 0x0000) -#define PLD_CFSTS __reg16(PLD_BASE + 0x0002) -#define PLD_CFIMASK __reg16(PLD_BASE + 0x0004) -#define PLD_CFBUFCR __reg16(PLD_BASE + 0x0006) - -/* MMC */ -#define PLD_MMCCR __reg16(PLD_BASE + 0x4000) -#define PLD_MMCMOD __reg16(PLD_BASE + 0x4002) -#define PLD_MMCSTS __reg16(PLD_BASE + 0x4006) -#define PLD_MMCBAUR __reg16(PLD_BASE + 0x400a) -#define PLD_MMCCMDBCUT __reg16(PLD_BASE + 0x400c) -#define PLD_MMCCDTBCUT __reg16(PLD_BASE + 0x400e) -#define PLD_MMCDET __reg16(PLD_BASE + 0x4010) -#define PLD_MMCWP __reg16(PLD_BASE + 0x4012) -#define PLD_MMCWDATA __reg16(PLD_BASE + 0x5000) -#define PLD_MMCRDATA __reg16(PLD_BASE + 0x6000) -#define PLD_MMCCMDDATA __reg16(PLD_BASE + 0x7000) -#define PLD_MMCRSPDATA __reg16(PLD_BASE + 0x7006) - -/* ICU - * ICUISTS: status register - * ICUIREQ0: request register - * ICUIREQ1: request register - * ICUCR3: control register for CFIREQ# interrupt - * ICUCR4: control register for CFC Card insert interrupt - * ICUCR5: control register for CFC Card eject interrupt - * ICUCR6: control register for external interrupt - * ICUCR11: control register for MMC Card insert/eject interrupt - * ICUCR13: control register for SC error interrupt - * ICUCR14: control register for SC receive interrupt - * ICUCR15: control register for SC send interrupt - */ - -#define PLD_IRQ_INT0 (M32104UT_PLD_IRQ_BASE + 0) /* None */ -#define PLD_IRQ_CFIREQ (M32104UT_PLD_IRQ_BASE + 3) /* CF IREQ */ -#define PLD_IRQ_CFC_INSERT (M32104UT_PLD_IRQ_BASE + 4) /* CF Insert */ -#define PLD_IRQ_CFC_EJECT (M32104UT_PLD_IRQ_BASE + 5) /* CF Eject */ -#define PLD_IRQ_EXINT (M32104UT_PLD_IRQ_BASE + 6) /* EXINT */ -#define PLD_IRQ_MMCCARD (M32104UT_PLD_IRQ_BASE + 11) /* MMC Insert/Eject */ -#define PLD_IRQ_SC_ERROR (M32104UT_PLD_IRQ_BASE + 13) /* SC error */ -#define PLD_IRQ_SC_RCV (M32104UT_PLD_IRQ_BASE + 14) /* SC receive */ -#define PLD_IRQ_SC_SND (M32104UT_PLD_IRQ_BASE + 15) /* SC send */ - -#define PLD_ICUISTS __reg16(PLD_BASE + 0x8002) -#define PLD_ICUISTS_VECB_MASK (0xf000) -#define PLD_ICUISTS_VECB(x) ((x) & PLD_ICUISTS_VECB_MASK) -#define PLD_ICUISTS_ISN_MASK (0x07c0) -#define PLD_ICUISTS_ISN(x) ((x) & PLD_ICUISTS_ISN_MASK) -#define PLD_ICUCR3 __reg16(PLD_BASE + 0x8104) -#define PLD_ICUCR4 __reg16(PLD_BASE + 0x8106) -#define PLD_ICUCR5 __reg16(PLD_BASE + 0x8108) -#define PLD_ICUCR6 __reg16(PLD_BASE + 0x810a) -#define PLD_ICUCR11 __reg16(PLD_BASE + 0x8114) -#define PLD_ICUCR13 __reg16(PLD_BASE + 0x8118) -#define PLD_ICUCR14 __reg16(PLD_BASE + 0x811a) -#define PLD_ICUCR15 __reg16(PLD_BASE + 0x811c) -#define PLD_ICUCR_IEN (0x1000) -#define PLD_ICUCR_IREQ (0x0100) -#define PLD_ICUCR_ISMOD00 (0x0000) /* Low edge */ -#define PLD_ICUCR_ISMOD01 (0x0010) /* Low level */ -#define PLD_ICUCR_ISMOD02 (0x0020) /* High edge */ -#define PLD_ICUCR_ISMOD03 (0x0030) /* High level */ -#define PLD_ICUCR_ILEVEL0 (0x0000) -#define PLD_ICUCR_ILEVEL1 (0x0001) -#define PLD_ICUCR_ILEVEL2 (0x0002) -#define PLD_ICUCR_ILEVEL3 (0x0003) -#define PLD_ICUCR_ILEVEL4 (0x0004) -#define PLD_ICUCR_ILEVEL5 (0x0005) -#define PLD_ICUCR_ILEVEL6 (0x0006) -#define PLD_ICUCR_ILEVEL7 (0x0007) - -/* Power Control of MMC and CF */ -#define PLD_CPCR __reg16(PLD_BASE + 0x14000) -#define PLD_CPCR_CDP 0x0001 - -/* LED Control - * - * 1: DIP swich side - * 2: Reset switch side - */ -#define PLD_IOLEDCR __reg16(PLD_BASE + 0x14002) -#define PLD_IOLED_1_ON 0x001 -#define PLD_IOLED_1_OFF 0x000 -#define PLD_IOLED_2_ON 0x002 -#define PLD_IOLED_2_OFF 0x000 - -/* DIP Switch - * 0: Write-protect of Flash Memory (0:protected, 1:non-protected) - * 1: - - * 2: - - * 3: - - */ -#define PLD_IOSWSTS __reg16(PLD_BASE + 0x14004) -#define PLD_IOSWSTS_IOSW2 0x0200 -#define PLD_IOSWSTS_IOSW1 0x0100 -#define PLD_IOSWSTS_IOWP0 0x0001 - -/* CRC */ -#define PLD_CRC7DATA __reg16(PLD_BASE + 0x18000) -#define PLD_CRC7INDATA __reg16(PLD_BASE + 0x18002) -#define PLD_CRC16DATA __reg16(PLD_BASE + 0x18004) -#define PLD_CRC16INDATA __reg16(PLD_BASE + 0x18006) -#define PLD_CRC16ADATA __reg16(PLD_BASE + 0x18008) -#define PLD_CRC16AINDATA __reg16(PLD_BASE + 0x1800a) - -/* RTC */ -#define PLD_RTCCR __reg16(PLD_BASE + 0x1c000) -#define PLD_RTCBAUR __reg16(PLD_BASE + 0x1c002) -#define PLD_RTCWRDATA __reg16(PLD_BASE + 0x1c004) -#define PLD_RTCRDDATA __reg16(PLD_BASE + 0x1c006) -#define PLD_RTCRSTODT __reg16(PLD_BASE + 0x1c008) - -/* SIM Card */ -#define PLD_SCCR __reg16(PLD_BASE + 0x38000) -#define PLD_SCMOD __reg16(PLD_BASE + 0x38004) -#define PLD_SCSTS __reg16(PLD_BASE + 0x38006) -#define PLD_SCINTCR __reg16(PLD_BASE + 0x38008) -#define PLD_SCBAUR __reg16(PLD_BASE + 0x3800a) -#define PLD_SCTXB __reg16(PLD_BASE + 0x3800c) -#define PLD_SCRXB __reg16(PLD_BASE + 0x3800e) - -#endif /* _M32104UT_M32104UT_PLD_H */ diff --git a/trunk/include/asm-m32r/m32r.h b/trunk/include/asm-m32r/m32r.h index b133ca61acf1..ec142be00862 100644 --- a/trunk/include/asm-m32r/m32r.h +++ b/trunk/include/asm-m32r/m32r.h @@ -14,7 +14,7 @@ #include #elif defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \ || defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \ - || defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104) + || defined(CONFIG_CHIP_OPSP) #include #endif @@ -43,10 +43,6 @@ #include #endif -#if defined(CONFIG_PLAT_M32104UT) -#include -#endif /* CONFIG_PLAT_M32104 */ - /* * M32R Register */ @@ -126,7 +122,7 @@ #include #ifdef CONFIG_MMU -#define NONCACHE_OFFSET (__PAGE_OFFSET + 0x20000000) +#define NONCACHE_OFFSET __PAGE_OFFSET+0x20000000 #else #define NONCACHE_OFFSET __PAGE_OFFSET #endif /* CONFIG_MMU */ diff --git a/trunk/include/asm-m32r/mman.h b/trunk/include/asm-m32r/mman.h index 12e29747bc84..011f6d9ec5cc 100644 --- a/trunk/include/asm-m32r/mman.h +++ b/trunk/include/asm-m32r/mman.h @@ -37,7 +37,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-m32r/system.h b/trunk/include/asm-m32r/system.h index dcf619a0a0b0..5eee832b73a0 100644 --- a/trunk/include/asm-m32r/system.h +++ b/trunk/include/asm-m32r/system.h @@ -69,12 +69,12 @@ } while(0) /* Interrupt Control */ -#if !defined(CONFIG_CHIP_M32102) && !defined(CONFIG_CHIP_M32104) +#if !defined(CONFIG_CHIP_M32102) #define local_irq_enable() \ __asm__ __volatile__ ("setpsw #0x40 -> nop": : :"memory") #define local_irq_disable() \ __asm__ __volatile__ ("clrpsw #0x40 -> nop": : :"memory") -#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ +#else /* CONFIG_CHIP_M32102 */ static inline void local_irq_enable(void) { unsigned long tmpreg; @@ -96,7 +96,7 @@ static inline void local_irq_disable(void) "mvtc %0, psw \n\t" : "=&r" (tmpreg0), "=&r" (tmpreg1) : : "cbit", "memory"); } -#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ +#endif /* CONFIG_CHIP_M32102 */ #define local_save_flags(x) \ __asm__ __volatile__("mvfc %0,psw" : "=r"(x) : /* no input */) @@ -105,13 +105,13 @@ static inline void local_irq_disable(void) __asm__ __volatile__("mvtc %0,psw" : /* no outputs */ \ : "r" (x) : "cbit", "memory") -#if !(defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_M32104)) +#if !defined(CONFIG_CHIP_M32102) #define local_irq_save(x) \ __asm__ __volatile__( \ "mvfc %0, psw; \n\t" \ "clrpsw #0x40 -> nop; \n\t" \ : "=r" (x) : /* no input */ : "memory") -#else /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ +#else /* CONFIG_CHIP_M32102 */ #define local_irq_save(x) \ ({ \ unsigned long tmpreg; \ @@ -124,7 +124,7 @@ static inline void local_irq_disable(void) : "=r" (x), "=&r" (tmpreg) \ : : "cbit", "memory"); \ }) -#endif /* CONFIG_CHIP_M32102 || CONFIG_CHIP_M32104 */ +#endif /* CONFIG_CHIP_M32102 */ #define irqs_disabled() \ ({ \ diff --git a/trunk/include/asm-m32r/unistd.h b/trunk/include/asm-m32r/unistd.h index 39be87ca2a5a..ac399e1f7bc0 100644 --- a/trunk/include/asm-m32r/unistd.h +++ b/trunk/include/asm-m32r/unistd.h @@ -319,7 +319,7 @@ type name(void) \ register long __scno __asm__ ("r7") = __NR_##name; \ register long __res __asm__("r0"); \ __asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ + "trap #" SYSCALL_VECTOR \ : "=r" (__res) \ : "r" (__scno) \ : "memory"); \ @@ -332,7 +332,7 @@ type name(type1 arg1) \ register long __scno __asm__ ("r7") = __NR_##name; \ register long __res __asm__ ("r0") = (long)(arg1); \ __asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ + "trap #" SYSCALL_VECTOR \ : "=r" (__res) \ : "r" (__scno), "0" (__res) \ : "memory"); \ @@ -346,7 +346,7 @@ register long __scno __asm__ ("r7") = __NR_##name; \ register long __arg2 __asm__ ("r1") = (long)(arg2); \ register long __res __asm__ ("r0") = (long)(arg1); \ __asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ + "trap #" SYSCALL_VECTOR \ : "=r" (__res) \ : "r" (__scno), "0" (__res), "r" (__arg2) \ : "memory"); \ @@ -361,7 +361,7 @@ register long __arg3 __asm__ ("r2") = (long)(arg3); \ register long __arg2 __asm__ ("r1") = (long)(arg2); \ register long __res __asm__ ("r0") = (long)(arg1); \ __asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ + "trap #" SYSCALL_VECTOR \ : "=r" (__res) \ : "r" (__scno), "0" (__res), "r" (__arg2), \ "r" (__arg3) \ @@ -378,7 +378,7 @@ register long __arg3 __asm__ ("r2") = (long)(arg3); \ register long __arg2 __asm__ ("r1") = (long)(arg2); \ register long __res __asm__ ("r0") = (long)(arg1); \ __asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ + "trap #" SYSCALL_VECTOR \ : "=r" (__res) \ : "r" (__scno), "0" (__res), "r" (__arg2), \ "r" (__arg3), "r" (__arg4) \ @@ -397,7 +397,7 @@ register long __arg3 __asm__ ("r2") = (long)(arg3); \ register long __arg2 __asm__ ("r1") = (long)(arg2); \ register long __res __asm__ ("r0") = (long)(arg1); \ __asm__ __volatile__ (\ - "trap #" SYSCALL_VECTOR "|| nop"\ + "trap #" SYSCALL_VECTOR \ : "=r" (__res) \ : "r" (__scno), "0" (__res), "r" (__arg2), \ "r" (__arg3), "r" (__arg4), "r" (__arg5) \ diff --git a/trunk/include/asm-m68k/atomic.h b/trunk/include/asm-m68k/atomic.h index b8a4e75d679d..e3c962eeabf3 100644 --- a/trunk/include/asm-m68k/atomic.h +++ b/trunk/include/asm-m68k/atomic.h @@ -157,5 +157,4 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif /* __ARCH_M68K_ATOMIC __ */ diff --git a/trunk/include/asm-m68k/irq.h b/trunk/include/asm-m68k/irq.h index 127ad190cf2d..1f569905cb74 100644 --- a/trunk/include/asm-m68k/irq.h +++ b/trunk/include/asm-m68k/irq.h @@ -70,6 +70,8 @@ static __inline__ int irq_canonicalize(int irq) extern void (*enable_irq)(unsigned int); extern void (*disable_irq)(unsigned int); + +#define disable_irq_nosync disable_irq #define enable_irq_nosync enable_irq struct pt_regs; diff --git a/trunk/include/asm-m68k/mman.h b/trunk/include/asm-m68k/mman.h index ea262ab88b3b..f831c4eeae6e 100644 --- a/trunk/include/asm-m68k/mman.h +++ b/trunk/include/asm-m68k/mman.h @@ -35,7 +35,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-m68knommu/atomic.h b/trunk/include/asm-m68knommu/atomic.h index 1702dbe9318c..3c1cc153c415 100644 --- a/trunk/include/asm-m68knommu/atomic.h +++ b/trunk/include/asm-m68knommu/atomic.h @@ -143,5 +143,4 @@ static inline int atomic_sub_return(int i, atomic_t * v) #define atomic_dec_return(v) atomic_sub_return(1,(v)) #define atomic_inc_return(v) atomic_add_return(1,(v)) -#include #endif /* __ARCH_M68KNOMMU_ATOMIC __ */ diff --git a/trunk/include/asm-m68knommu/irq.h b/trunk/include/asm-m68knommu/irq.h index 20c48ec858a4..a08fa9b958da 100644 --- a/trunk/include/asm-m68knommu/irq.h +++ b/trunk/include/asm-m68knommu/irq.h @@ -84,8 +84,10 @@ extern void (*mach_disable_irq)(unsigned int); /* * Some drivers want these entry points */ -#define enable_irq(x) 0 -#define disable_irq(x) do { } while (0) +#define enable_irq(x) (mach_enable_irq ? (*mach_enable_irq)(x) : 0) +#define disable_irq(x) (mach_disable_irq ? (*mach_disable_irq)(x) : 0) + +#define enable_irq_nosync(x) enable_irq(x) #define disable_irq_nosync(x) disable_irq(x) struct irqaction; diff --git a/trunk/include/asm-mips/atomic.h b/trunk/include/asm-mips/atomic.h index 92256e43a938..55c37c106ef0 100644 --- a/trunk/include/asm-mips/atomic.h +++ b/trunk/include/asm-mips/atomic.h @@ -713,5 +713,4 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) #define smp_mb__before_atomic_inc() smp_mb() #define smp_mb__after_atomic_inc() smp_mb() -#include #endif /* _ASM_ATOMIC_H */ diff --git a/trunk/include/asm-mips/mman.h b/trunk/include/asm-mips/mman.h index dd17c8bd62a1..62060957ba93 100644 --- a/trunk/include/asm-mips/mman.h +++ b/trunk/include/asm-mips/mman.h @@ -65,7 +65,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-mips/riscos-syscall.h b/trunk/include/asm-mips/riscos-syscall.h new file mode 100644 index 000000000000..4d8eb15461eb --- /dev/null +++ b/trunk/include/asm-mips/riscos-syscall.h @@ -0,0 +1,979 @@ +/* + * 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 archive + * for more details. + * + * Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle + */ +#ifndef _ASM_RISCOS_SYSCALL_H +#define _ASM_RISCOS_SYSCALL_H + +/* + * The syscalls 0 - 3999 are reserved for a down to the root syscall + * compatibility with RISC/os and IRIX. We'll see how to deal with the + * various "real" BSD variants like Ultrix, NetBSD ... + */ + +/* + * SVR4 syscalls are in the range from 1 to 999 + */ +#define __NR_SVR4 0 +#define __NR_SVR4_syscall (__NR_SVR4 + 0) +#define __NR_SVR4_exit (__NR_SVR4 + 1) +#define __NR_SVR4_fork (__NR_SVR4 + 2) +#define __NR_SVR4_read (__NR_SVR4 + 3) +#define __NR_SVR4_write (__NR_SVR4 + 4) +#define __NR_SVR4_open (__NR_SVR4 + 5) +#define __NR_SVR4_close (__NR_SVR4 + 6) +#define __NR_SVR4_wait (__NR_SVR4 + 7) +#define __NR_SVR4_creat (__NR_SVR4 + 8) +#define __NR_SVR4_link (__NR_SVR4 + 9) +#define __NR_SVR4_unlink (__NR_SVR4 + 10) +#define __NR_SVR4_exec (__NR_SVR4 + 11) +#define __NR_SVR4_chdir (__NR_SVR4 + 12) +#define __NR_SVR4_gtime (__NR_SVR4 + 13) +#define __NR_SVR4_mknod (__NR_SVR4 + 14) +#define __NR_SVR4_chmod (__NR_SVR4 + 15) +#define __NR_SVR4_chown (__NR_SVR4 + 16) +#define __NR_SVR4_sbreak (__NR_SVR4 + 17) +#define __NR_SVR4_stat (__NR_SVR4 + 18) +#define __NR_SVR4_lseek (__NR_SVR4 + 19) +#define __NR_SVR4_getpid (__NR_SVR4 + 20) +#define __NR_SVR4_mount (__NR_SVR4 + 21) +#define __NR_SVR4_umount (__NR_SVR4 + 22) +#define __NR_SVR4_setuid (__NR_SVR4 + 23) +#define __NR_SVR4_getuid (__NR_SVR4 + 24) +#define __NR_SVR4_stime (__NR_SVR4 + 25) +#define __NR_SVR4_ptrace (__NR_SVR4 + 26) +#define __NR_SVR4_alarm (__NR_SVR4 + 27) +#define __NR_SVR4_fstat (__NR_SVR4 + 28) +#define __NR_SVR4_pause (__NR_SVR4 + 29) +#define __NR_SVR4_utime (__NR_SVR4 + 30) +#define __NR_SVR4_stty (__NR_SVR4 + 31) +#define __NR_SVR4_gtty (__NR_SVR4 + 32) +#define __NR_SVR4_access (__NR_SVR4 + 33) +#define __NR_SVR4_nice (__NR_SVR4 + 34) +#define __NR_SVR4_statfs (__NR_SVR4 + 35) +#define __NR_SVR4_sync (__NR_SVR4 + 36) +#define __NR_SVR4_kill (__NR_SVR4 + 37) +#define __NR_SVR4_fstatfs (__NR_SVR4 + 38) +#define __NR_SVR4_setpgrp (__NR_SVR4 + 39) +#define __NR_SVR4_cxenix (__NR_SVR4 + 40) +#define __NR_SVR4_dup (__NR_SVR4 + 41) +#define __NR_SVR4_pipe (__NR_SVR4 + 42) +#define __NR_SVR4_times (__NR_SVR4 + 43) +#define __NR_SVR4_profil (__NR_SVR4 + 44) +#define __NR_SVR4_plock (__NR_SVR4 + 45) +#define __NR_SVR4_setgid (__NR_SVR4 + 46) +#define __NR_SVR4_getgid (__NR_SVR4 + 47) +#define __NR_SVR4_sig (__NR_SVR4 + 48) +#define __NR_SVR4_msgsys (__NR_SVR4 + 49) +#define __NR_SVR4_sysmips (__NR_SVR4 + 50) +#define __NR_SVR4_sysacct (__NR_SVR4 + 51) +#define __NR_SVR4_shmsys (__NR_SVR4 + 52) +#define __NR_SVR4_semsys (__NR_SVR4 + 53) +#define __NR_SVR4_ioctl (__NR_SVR4 + 54) +#define __NR_SVR4_uadmin (__NR_SVR4 + 55) +#define __NR_SVR4_exch (__NR_SVR4 + 56) +#define __NR_SVR4_utssys (__NR_SVR4 + 57) +#define __NR_SVR4_fsync (__NR_SVR4 + 58) +#define __NR_SVR4_exece (__NR_SVR4 + 59) +#define __NR_SVR4_umask (__NR_SVR4 + 60) +#define __NR_SVR4_chroot (__NR_SVR4 + 61) +#define __NR_SVR4_fcntl (__NR_SVR4 + 62) +#define __NR_SVR4_ulimit (__NR_SVR4 + 63) +#define __NR_SVR4_reserved1 (__NR_SVR4 + 64) +#define __NR_SVR4_reserved2 (__NR_SVR4 + 65) +#define __NR_SVR4_reserved3 (__NR_SVR4 + 66) +#define __NR_SVR4_reserved4 (__NR_SVR4 + 67) +#define __NR_SVR4_reserved5 (__NR_SVR4 + 68) +#define __NR_SVR4_reserved6 (__NR_SVR4 + 69) +#define __NR_SVR4_advfs (__NR_SVR4 + 70) +#define __NR_SVR4_unadvfs (__NR_SVR4 + 71) +#define __NR_SVR4_unused1 (__NR_SVR4 + 72) +#define __NR_SVR4_unused2 (__NR_SVR4 + 73) +#define __NR_SVR4_rfstart (__NR_SVR4 + 74) +#define __NR_SVR4_unused3 (__NR_SVR4 + 75) +#define __NR_SVR4_rdebug (__NR_SVR4 + 76) +#define __NR_SVR4_rfstop (__NR_SVR4 + 77) +#define __NR_SVR4_rfsys (__NR_SVR4 + 78) +#define __NR_SVR4_rmdir (__NR_SVR4 + 79) +#define __NR_SVR4_mkdir (__NR_SVR4 + 80) +#define __NR_SVR4_getdents (__NR_SVR4 + 81) +#define __NR_SVR4_libattach (__NR_SVR4 + 82) +#define __NR_SVR4_libdetach (__NR_SVR4 + 83) +#define __NR_SVR4_sysfs (__NR_SVR4 + 84) +#define __NR_SVR4_getmsg (__NR_SVR4 + 85) +#define __NR_SVR4_putmsg (__NR_SVR4 + 86) +#define __NR_SVR4_poll (__NR_SVR4 + 87) +#define __NR_SVR4_lstat (__NR_SVR4 + 88) +#define __NR_SVR4_symlink (__NR_SVR4 + 89) +#define __NR_SVR4_readlink (__NR_SVR4 + 90) +#define __NR_SVR4_setgroups (__NR_SVR4 + 91) +#define __NR_SVR4_getgroups (__NR_SVR4 + 92) +#define __NR_SVR4_fchmod (__NR_SVR4 + 93) +#define __NR_SVR4_fchown (__NR_SVR4 + 94) +#define __NR_SVR4_sigprocmask (__NR_SVR4 + 95) +#define __NR_SVR4_sigsuspend (__NR_SVR4 + 96) +#define __NR_SVR4_sigaltstack (__NR_SVR4 + 97) +#define __NR_SVR4_sigaction (__NR_SVR4 + 98) +#define __NR_SVR4_sigpending (__NR_SVR4 + 99) +#define __NR_SVR4_setcontext (__NR_SVR4 + 100) +#define __NR_SVR4_evsys (__NR_SVR4 + 101) +#define __NR_SVR4_evtrapret (__NR_SVR4 + 102) +#define __NR_SVR4_statvfs (__NR_SVR4 + 103) +#define __NR_SVR4_fstatvfs (__NR_SVR4 + 104) +#define __NR_SVR4_reserved7 (__NR_SVR4 + 105) +#define __NR_SVR4_nfssys (__NR_SVR4 + 106) +#define __NR_SVR4_waitid (__NR_SVR4 + 107) +#define __NR_SVR4_sigsendset (__NR_SVR4 + 108) +#define __NR_SVR4_hrtsys (__NR_SVR4 + 109) +#define __NR_SVR4_acancel (__NR_SVR4 + 110) +#define __NR_SVR4_async (__NR_SVR4 + 111) +#define __NR_SVR4_priocntlset (__NR_SVR4 + 112) +#define __NR_SVR4_pathconf (__NR_SVR4 + 113) +#define __NR_SVR4_mincore (__NR_SVR4 + 114) +#define __NR_SVR4_mmap (__NR_SVR4 + 115) +#define __NR_SVR4_mprotect (__NR_SVR4 + 116) +#define __NR_SVR4_munmap (__NR_SVR4 + 117) +#define __NR_SVR4_fpathconf (__NR_SVR4 + 118) +#define __NR_SVR4_vfork (__NR_SVR4 + 119) +#define __NR_SVR4_fchdir (__NR_SVR4 + 120) +#define __NR_SVR4_readv (__NR_SVR4 + 121) +#define __NR_SVR4_writev (__NR_SVR4 + 122) +#define __NR_SVR4_xstat (__NR_SVR4 + 123) +#define __NR_SVR4_lxstat (__NR_SVR4 + 124) +#define __NR_SVR4_fxstat (__NR_SVR4 + 125) +#define __NR_SVR4_xmknod (__NR_SVR4 + 126) +#define __NR_SVR4_clocal (__NR_SVR4 + 127) +#define __NR_SVR4_setrlimit (__NR_SVR4 + 128) +#define __NR_SVR4_getrlimit (__NR_SVR4 + 129) +#define __NR_SVR4_lchown (__NR_SVR4 + 130) +#define __NR_SVR4_memcntl (__NR_SVR4 + 131) +#define __NR_SVR4_getpmsg (__NR_SVR4 + 132) +#define __NR_SVR4_putpmsg (__NR_SVR4 + 133) +#define __NR_SVR4_rename (__NR_SVR4 + 134) +#define __NR_SVR4_nuname (__NR_SVR4 + 135) +#define __NR_SVR4_setegid (__NR_SVR4 + 136) +#define __NR_SVR4_sysconf (__NR_SVR4 + 137) +#define __NR_SVR4_adjtime (__NR_SVR4 + 138) +#define __NR_SVR4_sysinfo (__NR_SVR4 + 139) +#define __NR_SVR4_reserved8 (__NR_SVR4 + 140) +#define __NR_SVR4_seteuid (__NR_SVR4 + 141) +#define __NR_SVR4_PYRAMID_statis (__NR_SVR4 + 142) +#define __NR_SVR4_PYRAMID_tuning (__NR_SVR4 + 143) +#define __NR_SVR4_PYRAMID_forcerr (__NR_SVR4 + 144) +#define __NR_SVR4_PYRAMID_mpcntl (__NR_SVR4 + 145) +#define __NR_SVR4_reserved9 (__NR_SVR4 + 146) +#define __NR_SVR4_reserved10 (__NR_SVR4 + 147) +#define __NR_SVR4_reserved11 (__NR_SVR4 + 148) +#define __NR_SVR4_reserved12 (__NR_SVR4 + 149) +#define __NR_SVR4_reserved13 (__NR_SVR4 + 150) +#define __NR_SVR4_reserved14 (__NR_SVR4 + 151) +#define __NR_SVR4_reserved15 (__NR_SVR4 + 152) +#define __NR_SVR4_reserved16 (__NR_SVR4 + 153) +#define __NR_SVR4_reserved17 (__NR_SVR4 + 154) +#define __NR_SVR4_reserved18 (__NR_SVR4 + 155) +#define __NR_SVR4_reserved19 (__NR_SVR4 + 156) +#define __NR_SVR4_reserved20 (__NR_SVR4 + 157) +#define __NR_SVR4_reserved21 (__NR_SVR4 + 158) +#define __NR_SVR4_reserved22 (__NR_SVR4 + 159) +#define __NR_SVR4_reserved23 (__NR_SVR4 + 160) +#define __NR_SVR4_reserved24 (__NR_SVR4 + 161) +#define __NR_SVR4_reserved25 (__NR_SVR4 + 162) +#define __NR_SVR4_reserved26 (__NR_SVR4 + 163) +#define __NR_SVR4_reserved27 (__NR_SVR4 + 164) +#define __NR_SVR4_reserved28 (__NR_SVR4 + 165) +#define __NR_SVR4_reserved29 (__NR_SVR4 + 166) +#define __NR_SVR4_reserved30 (__NR_SVR4 + 167) +#define __NR_SVR4_reserved31 (__NR_SVR4 + 168) +#define __NR_SVR4_reserved32 (__NR_SVR4 + 169) +#define __NR_SVR4_reserved33 (__NR_SVR4 + 170) +#define __NR_SVR4_reserved34 (__NR_SVR4 + 171) +#define __NR_SVR4_reserved35 (__NR_SVR4 + 172) +#define __NR_SVR4_reserved36 (__NR_SVR4 + 173) +#define __NR_SVR4_reserved37 (__NR_SVR4 + 174) +#define __NR_SVR4_reserved38 (__NR_SVR4 + 175) +#define __NR_SVR4_reserved39 (__NR_SVR4 + 176) +#define __NR_SVR4_reserved40 (__NR_SVR4 + 177) +#define __NR_SVR4_reserved41 (__NR_SVR4 + 178) +#define __NR_SVR4_reserved42 (__NR_SVR4 + 179) +#define __NR_SVR4_reserved43 (__NR_SVR4 + 180) +#define __NR_SVR4_reserved44 (__NR_SVR4 + 181) +#define __NR_SVR4_reserved45 (__NR_SVR4 + 182) +#define __NR_SVR4_reserved46 (__NR_SVR4 + 183) +#define __NR_SVR4_reserved47 (__NR_SVR4 + 184) +#define __NR_SVR4_reserved48 (__NR_SVR4 + 185) +#define __NR_SVR4_reserved49 (__NR_SVR4 + 186) +#define __NR_SVR4_reserved50 (__NR_SVR4 + 187) +#define __NR_SVR4_reserved51 (__NR_SVR4 + 188) +#define __NR_SVR4_reserved52 (__NR_SVR4 + 189) +#define __NR_SVR4_reserved53 (__NR_SVR4 + 190) +#define __NR_SVR4_reserved54 (__NR_SVR4 + 191) +#define __NR_SVR4_reserved55 (__NR_SVR4 + 192) +#define __NR_SVR4_reserved56 (__NR_SVR4 + 193) +#define __NR_SVR4_reserved57 (__NR_SVR4 + 194) +#define __NR_SVR4_reserved58 (__NR_SVR4 + 195) +#define __NR_SVR4_reserved59 (__NR_SVR4 + 196) +#define __NR_SVR4_reserved60 (__NR_SVR4 + 197) +#define __NR_SVR4_reserved61 (__NR_SVR4 + 198) +#define __NR_SVR4_reserved62 (__NR_SVR4 + 199) +#define __NR_SVR4_reserved63 (__NR_SVR4 + 200) +#define __NR_SVR4_aread (__NR_SVR4 + 201) +#define __NR_SVR4_awrite (__NR_SVR4 + 202) +#define __NR_SVR4_listio (__NR_SVR4 + 203) +#define __NR_SVR4_mips_acancel (__NR_SVR4 + 204) +#define __NR_SVR4_astatus (__NR_SVR4 + 205) +#define __NR_SVR4_await (__NR_SVR4 + 206) +#define __NR_SVR4_areadv (__NR_SVR4 + 207) +#define __NR_SVR4_awritev (__NR_SVR4 + 208) +#define __NR_SVR4_MIPS_reserved1 (__NR_SVR4 + 209) +#define __NR_SVR4_MIPS_reserved2 (__NR_SVR4 + 210) +#define __NR_SVR4_MIPS_reserved3 (__NR_SVR4 + 211) +#define __NR_SVR4_MIPS_reserved4 (__NR_SVR4 + 212) +#define __NR_SVR4_MIPS_reserved5 (__NR_SVR4 + 213) +#define __NR_SVR4_MIPS_reserved6 (__NR_SVR4 + 214) +#define __NR_SVR4_MIPS_reserved7 (__NR_SVR4 + 215) +#define __NR_SVR4_MIPS_reserved8 (__NR_SVR4 + 216) +#define __NR_SVR4_MIPS_reserved9 (__NR_SVR4 + 217) +#define __NR_SVR4_MIPS_reserved10 (__NR_SVR4 + 218) +#define __NR_SVR4_MIPS_reserved11 (__NR_SVR4 + 219) +#define __NR_SVR4_MIPS_reserved12 (__NR_SVR4 + 220) +#define __NR_SVR4_CDC_reserved1 (__NR_SVR4 + 221) +#define __NR_SVR4_CDC_reserved2 (__NR_SVR4 + 222) +#define __NR_SVR4_CDC_reserved3 (__NR_SVR4 + 223) +#define __NR_SVR4_CDC_reserved4 (__NR_SVR4 + 224) +#define __NR_SVR4_CDC_reserved5 (__NR_SVR4 + 225) +#define __NR_SVR4_CDC_reserved6 (__NR_SVR4 + 226) +#define __NR_SVR4_CDC_reserved7 (__NR_SVR4 + 227) +#define __NR_SVR4_CDC_reserved8 (__NR_SVR4 + 228) +#define __NR_SVR4_CDC_reserved9 (__NR_SVR4 + 229) +#define __NR_SVR4_CDC_reserved10 (__NR_SVR4 + 230) +#define __NR_SVR4_CDC_reserved11 (__NR_SVR4 + 231) +#define __NR_SVR4_CDC_reserved12 (__NR_SVR4 + 232) +#define __NR_SVR4_CDC_reserved13 (__NR_SVR4 + 233) +#define __NR_SVR4_CDC_reserved14 (__NR_SVR4 + 234) +#define __NR_SVR4_CDC_reserved15 (__NR_SVR4 + 235) +#define __NR_SVR4_CDC_reserved16 (__NR_SVR4 + 236) +#define __NR_SVR4_CDC_reserved17 (__NR_SVR4 + 237) +#define __NR_SVR4_CDC_reserved18 (__NR_SVR4 + 238) +#define __NR_SVR4_CDC_reserved19 (__NR_SVR4 + 239) +#define __NR_SVR4_CDC_reserved20 (__NR_SVR4 + 240) + +/* + * SYS V syscalls are in the range from 1000 to 1999 + */ +#define __NR_SYSV 1000 +#define __NR_SYSV_syscall (__NR_SYSV + 0) +#define __NR_SYSV_exit (__NR_SYSV + 1) +#define __NR_SYSV_fork (__NR_SYSV + 2) +#define __NR_SYSV_read (__NR_SYSV + 3) +#define __NR_SYSV_write (__NR_SYSV + 4) +#define __NR_SYSV_open (__NR_SYSV + 5) +#define __NR_SYSV_close (__NR_SYSV + 6) +#define __NR_SYSV_wait (__NR_SYSV + 7) +#define __NR_SYSV_creat (__NR_SYSV + 8) +#define __NR_SYSV_link (__NR_SYSV + 9) +#define __NR_SYSV_unlink (__NR_SYSV + 10) +#define __NR_SYSV_execv (__NR_SYSV + 11) +#define __NR_SYSV_chdir (__NR_SYSV + 12) +#define __NR_SYSV_time (__NR_SYSV + 13) +#define __NR_SYSV_mknod (__NR_SYSV + 14) +#define __NR_SYSV_chmod (__NR_SYSV + 15) +#define __NR_SYSV_chown (__NR_SYSV + 16) +#define __NR_SYSV_brk (__NR_SYSV + 17) +#define __NR_SYSV_stat (__NR_SYSV + 18) +#define __NR_SYSV_lseek (__NR_SYSV + 19) +#define __NR_SYSV_getpid (__NR_SYSV + 20) +#define __NR_SYSV_mount (__NR_SYSV + 21) +#define __NR_SYSV_umount (__NR_SYSV + 22) +#define __NR_SYSV_setuid (__NR_SYSV + 23) +#define __NR_SYSV_getuid (__NR_SYSV + 24) +#define __NR_SYSV_stime (__NR_SYSV + 25) +#define __NR_SYSV_ptrace (__NR_SYSV + 26) +#define __NR_SYSV_alarm (__NR_SYSV + 27) +#define __NR_SYSV_fstat (__NR_SYSV + 28) +#define __NR_SYSV_pause (__NR_SYSV + 29) +#define __NR_SYSV_utime (__NR_SYSV + 30) +#define __NR_SYSV_stty (__NR_SYSV + 31) +#define __NR_SYSV_gtty (__NR_SYSV + 32) +#define __NR_SYSV_access (__NR_SYSV + 33) +#define __NR_SYSV_nice (__NR_SYSV + 34) +#define __NR_SYSV_statfs (__NR_SYSV + 35) +#define __NR_SYSV_sync (__NR_SYSV + 36) +#define __NR_SYSV_kill (__NR_SYSV + 37) +#define __NR_SYSV_fstatfs (__NR_SYSV + 38) +#define __NR_SYSV_setpgrp (__NR_SYSV + 39) +#define __NR_SYSV_syssgi (__NR_SYSV + 40) +#define __NR_SYSV_dup (__NR_SYSV + 41) +#define __NR_SYSV_pipe (__NR_SYSV + 42) +#define __NR_SYSV_times (__NR_SYSV + 43) +#define __NR_SYSV_profil (__NR_SYSV + 44) +#define __NR_SYSV_plock (__NR_SYSV + 45) +#define __NR_SYSV_setgid (__NR_SYSV + 46) +#define __NR_SYSV_getgid (__NR_SYSV + 47) +#define __NR_SYSV_sig (__NR_SYSV + 48) +#define __NR_SYSV_msgsys (__NR_SYSV + 49) +#define __NR_SYSV_sysmips (__NR_SYSV + 50) +#define __NR_SYSV_acct (__NR_SYSV + 51) +#define __NR_SYSV_shmsys (__NR_SYSV + 52) +#define __NR_SYSV_semsys (__NR_SYSV + 53) +#define __NR_SYSV_ioctl (__NR_SYSV + 54) +#define __NR_SYSV_uadmin (__NR_SYSV + 55) +#define __NR_SYSV_sysmp (__NR_SYSV + 56) +#define __NR_SYSV_utssys (__NR_SYSV + 57) +#define __NR_SYSV_USG_reserved1 (__NR_SYSV + 58) +#define __NR_SYSV_execve (__NR_SYSV + 59) +#define __NR_SYSV_umask (__NR_SYSV + 60) +#define __NR_SYSV_chroot (__NR_SYSV + 61) +#define __NR_SYSV_fcntl (__NR_SYSV + 62) +#define __NR_SYSV_ulimit (__NR_SYSV + 63) +#define __NR_SYSV_SAFARI4_reserved1 (__NR_SYSV + 64) +#define __NR_SYSV_SAFARI4_reserved2 (__NR_SYSV + 65) +#define __NR_SYSV_SAFARI4_reserved3 (__NR_SYSV + 66) +#define __NR_SYSV_SAFARI4_reserved4 (__NR_SYSV + 67) +#define __NR_SYSV_SAFARI4_reserved5 (__NR_SYSV + 68) +#define __NR_SYSV_SAFARI4_reserved6 (__NR_SYSV + 69) +#define __NR_SYSV_advfs (__NR_SYSV + 70) +#define __NR_SYSV_unadvfs (__NR_SYSV + 71) +#define __NR_SYSV_rmount (__NR_SYSV + 72) +#define __NR_SYSV_rumount (__NR_SYSV + 73) +#define __NR_SYSV_rfstart (__NR_SYSV + 74) +#define __NR_SYSV_getrlimit64 (__NR_SYSV + 75) +#define __NR_SYSV_setrlimit64 (__NR_SYSV + 76) +#define __NR_SYSV_nanosleep (__NR_SYSV + 77) +#define __NR_SYSV_lseek64 (__NR_SYSV + 78) +#define __NR_SYSV_rmdir (__NR_SYSV + 79) +#define __NR_SYSV_mkdir (__NR_SYSV + 80) +#define __NR_SYSV_getdents (__NR_SYSV + 81) +#define __NR_SYSV_sginap (__NR_SYSV + 82) +#define __NR_SYSV_sgikopt (__NR_SYSV + 83) +#define __NR_SYSV_sysfs (__NR_SYSV + 84) +#define __NR_SYSV_getmsg (__NR_SYSV + 85) +#define __NR_SYSV_putmsg (__NR_SYSV + 86) +#define __NR_SYSV_poll (__NR_SYSV + 87) +#define __NR_SYSV_sigreturn (__NR_SYSV + 88) +#define __NR_SYSV_accept (__NR_SYSV + 89) +#define __NR_SYSV_bind (__NR_SYSV + 90) +#define __NR_SYSV_connect (__NR_SYSV + 91) +#define __NR_SYSV_gethostid (__NR_SYSV + 92) +#define __NR_SYSV_getpeername (__NR_SYSV + 93) +#define __NR_SYSV_getsockname (__NR_SYSV + 94) +#define __NR_SYSV_getsockopt (__NR_SYSV + 95) +#define __NR_SYSV_listen (__NR_SYSV + 96) +#define __NR_SYSV_recv (__NR_SYSV + 97) +#define __NR_SYSV_recvfrom (__NR_SYSV + 98) +#define __NR_SYSV_recvmsg (__NR_SYSV + 99) +#define __NR_SYSV_select (__NR_SYSV + 100) +#define __NR_SYSV_send (__NR_SYSV + 101) +#define __NR_SYSV_sendmsg (__NR_SYSV + 102) +#define __NR_SYSV_sendto (__NR_SYSV + 103) +#define __NR_SYSV_sethostid (__NR_SYSV + 104) +#define __NR_SYSV_setsockopt (__NR_SYSV + 105) +#define __NR_SYSV_shutdown (__NR_SYSV + 106) +#define __NR_SYSV_socket (__NR_SYSV + 107) +#define __NR_SYSV_gethostname (__NR_SYSV + 108) +#define __NR_SYSV_sethostname (__NR_SYSV + 109) +#define __NR_SYSV_getdomainname (__NR_SYSV + 110) +#define __NR_SYSV_setdomainname (__NR_SYSV + 111) +#define __NR_SYSV_truncate (__NR_SYSV + 112) +#define __NR_SYSV_ftruncate (__NR_SYSV + 113) +#define __NR_SYSV_rename (__NR_SYSV + 114) +#define __NR_SYSV_symlink (__NR_SYSV + 115) +#define __NR_SYSV_readlink (__NR_SYSV + 116) +#define __NR_SYSV_lstat (__NR_SYSV + 117) +#define __NR_SYSV_nfsmount (__NR_SYSV + 118) +#define __NR_SYSV_nfssvc (__NR_SYSV + 119) +#define __NR_SYSV_getfh (__NR_SYSV + 120) +#define __NR_SYSV_async_daemon (__NR_SYSV + 121) +#define __NR_SYSV_exportfs (__NR_SYSV + 122) +#define __NR_SYSV_setregid (__NR_SYSV + 123) +#define __NR_SYSV_setreuid (__NR_SYSV + 124) +#define __NR_SYSV_getitimer (__NR_SYSV + 125) +#define __NR_SYSV_setitimer (__NR_SYSV + 126) +#define __NR_SYSV_adjtime (__NR_SYSV + 127) +#define __NR_SYSV_BSD_getime (__NR_SYSV + 128) +#define __NR_SYSV_sproc (__NR_SYSV + 129) +#define __NR_SYSV_prctl (__NR_SYSV + 130) +#define __NR_SYSV_procblk (__NR_SYSV + 131) +#define __NR_SYSV_sprocsp (__NR_SYSV + 132) +#define __NR_SYSV_sgigsc (__NR_SYSV + 133) +#define __NR_SYSV_mmap (__NR_SYSV + 134) +#define __NR_SYSV_munmap (__NR_SYSV + 135) +#define __NR_SYSV_mprotect (__NR_SYSV + 136) +#define __NR_SYSV_msync (__NR_SYSV + 137) +#define __NR_SYSV_madvise (__NR_SYSV + 138) +#define __NR_SYSV_pagelock (__NR_SYSV + 139) +#define __NR_SYSV_getpagesize (__NR_SYSV + 140) +#define __NR_SYSV_quotactl (__NR_SYSV + 141) +#define __NR_SYSV_libdetach (__NR_SYSV + 142) +#define __NR_SYSV_BSDgetpgrp (__NR_SYSV + 143) +#define __NR_SYSV_BSDsetpgrp (__NR_SYSV + 144) +#define __NR_SYSV_vhangup (__NR_SYSV + 145) +#define __NR_SYSV_fsync (__NR_SYSV + 146) +#define __NR_SYSV_fchdir (__NR_SYSV + 147) +#define __NR_SYSV_getrlimit (__NR_SYSV + 148) +#define __NR_SYSV_setrlimit (__NR_SYSV + 149) +#define __NR_SYSV_cacheflush (__NR_SYSV + 150) +#define __NR_SYSV_cachectl (__NR_SYSV + 151) +#define __NR_SYSV_fchown (__NR_SYSV + 152) +#define __NR_SYSV_fchmod (__NR_SYSV + 153) +#define __NR_SYSV_wait3 (__NR_SYSV + 154) +#define __NR_SYSV_socketpair (__NR_SYSV + 155) +#define __NR_SYSV_sysinfo (__NR_SYSV + 156) +#define __NR_SYSV_nuname (__NR_SYSV + 157) +#define __NR_SYSV_xstat (__NR_SYSV + 158) +#define __NR_SYSV_lxstat (__NR_SYSV + 159) +#define __NR_SYSV_fxstat (__NR_SYSV + 160) +#define __NR_SYSV_xmknod (__NR_SYSV + 161) +#define __NR_SYSV_ksigaction (__NR_SYSV + 162) +#define __NR_SYSV_sigpending (__NR_SYSV + 163) +#define __NR_SYSV_sigprocmask (__NR_SYSV + 164) +#define __NR_SYSV_sigsuspend (__NR_SYSV + 165) +#define __NR_SYSV_sigpoll (__NR_SYSV + 166) +#define __NR_SYSV_swapctl (__NR_SYSV + 167) +#define __NR_SYSV_getcontext (__NR_SYSV + 168) +#define __NR_SYSV_setcontext (__NR_SYSV + 169) +#define __NR_SYSV_waitsys (__NR_SYSV + 170) +#define __NR_SYSV_sigstack (__NR_SYSV + 171) +#define __NR_SYSV_sigaltstack (__NR_SYSV + 172) +#define __NR_SYSV_sigsendset (__NR_SYSV + 173) +#define __NR_SYSV_statvfs (__NR_SYSV + 174) +#define __NR_SYSV_fstatvfs (__NR_SYSV + 175) +#define __NR_SYSV_getpmsg (__NR_SYSV + 176) +#define __NR_SYSV_putpmsg (__NR_SYSV + 177) +#define __NR_SYSV_lchown (__NR_SYSV + 178) +#define __NR_SYSV_priocntl (__NR_SYSV + 179) +#define __NR_SYSV_ksigqueue (__NR_SYSV + 180) +#define __NR_SYSV_readv (__NR_SYSV + 181) +#define __NR_SYSV_writev (__NR_SYSV + 182) +#define __NR_SYSV_truncate64 (__NR_SYSV + 183) +#define __NR_SYSV_ftruncate64 (__NR_SYSV + 184) +#define __NR_SYSV_mmap64 (__NR_SYSV + 185) +#define __NR_SYSV_dmi (__NR_SYSV + 186) +#define __NR_SYSV_pread (__NR_SYSV + 187) +#define __NR_SYSV_pwrite (__NR_SYSV + 188) + +/* + * BSD 4.3 syscalls are in the range from 2000 to 2999 + */ +#define __NR_BSD43 2000 +#define __NR_BSD43_syscall (__NR_BSD43 + 0) +#define __NR_BSD43_exit (__NR_BSD43 + 1) +#define __NR_BSD43_fork (__NR_BSD43 + 2) +#define __NR_BSD43_read (__NR_BSD43 + 3) +#define __NR_BSD43_write (__NR_BSD43 + 4) +#define __NR_BSD43_open (__NR_BSD43 + 5) +#define __NR_BSD43_close (__NR_BSD43 + 6) +#define __NR_BSD43_wait (__NR_BSD43 + 7) +#define __NR_BSD43_creat (__NR_BSD43 + 8) +#define __NR_BSD43_link (__NR_BSD43 + 9) +#define __NR_BSD43_unlink (__NR_BSD43 + 10) +#define __NR_BSD43_exec (__NR_BSD43 + 11) +#define __NR_BSD43_chdir (__NR_BSD43 + 12) +#define __NR_BSD43_time (__NR_BSD43 + 13) +#define __NR_BSD43_mknod (__NR_BSD43 + 14) +#define __NR_BSD43_chmod (__NR_BSD43 + 15) +#define __NR_BSD43_chown (__NR_BSD43 + 16) +#define __NR_BSD43_sbreak (__NR_BSD43 + 17) +#define __NR_BSD43_oldstat (__NR_BSD43 + 18) +#define __NR_BSD43_lseek (__NR_BSD43 + 19) +#define __NR_BSD43_getpid (__NR_BSD43 + 20) +#define __NR_BSD43_oldmount (__NR_BSD43 + 21) +#define __NR_BSD43_umount (__NR_BSD43 + 22) +#define __NR_BSD43_setuid (__NR_BSD43 + 23) +#define __NR_BSD43_getuid (__NR_BSD43 + 24) +#define __NR_BSD43_stime (__NR_BSD43 + 25) +#define __NR_BSD43_ptrace (__NR_BSD43 + 26) +#define __NR_BSD43_alarm (__NR_BSD43 + 27) +#define __NR_BSD43_oldfstat (__NR_BSD43 + 28) +#define __NR_BSD43_pause (__NR_BSD43 + 29) +#define __NR_BSD43_utime (__NR_BSD43 + 30) +#define __NR_BSD43_stty (__NR_BSD43 + 31) +#define __NR_BSD43_gtty (__NR_BSD43 + 32) +#define __NR_BSD43_access (__NR_BSD43 + 33) +#define __NR_BSD43_nice (__NR_BSD43 + 34) +#define __NR_BSD43_ftime (__NR_BSD43 + 35) +#define __NR_BSD43_sync (__NR_BSD43 + 36) +#define __NR_BSD43_kill (__NR_BSD43 + 37) +#define __NR_BSD43_stat (__NR_BSD43 + 38) +#define __NR_BSD43_oldsetpgrp (__NR_BSD43 + 39) +#define __NR_BSD43_lstat (__NR_BSD43 + 40) +#define __NR_BSD43_dup (__NR_BSD43 + 41) +#define __NR_BSD43_pipe (__NR_BSD43 + 42) +#define __NR_BSD43_times (__NR_BSD43 + 43) +#define __NR_BSD43_profil (__NR_BSD43 + 44) +#define __NR_BSD43_msgsys (__NR_BSD43 + 45) +#define __NR_BSD43_setgid (__NR_BSD43 + 46) +#define __NR_BSD43_getgid (__NR_BSD43 + 47) +#define __NR_BSD43_ssig (__NR_BSD43 + 48) +#define __NR_BSD43_reserved1 (__NR_BSD43 + 49) +#define __NR_BSD43_reserved2 (__NR_BSD43 + 50) +#define __NR_BSD43_sysacct (__NR_BSD43 + 51) +#define __NR_BSD43_phys (__NR_BSD43 + 52) +#define __NR_BSD43_lock (__NR_BSD43 + 53) +#define __NR_BSD43_ioctl (__NR_BSD43 + 54) +#define __NR_BSD43_reboot (__NR_BSD43 + 55) +#define __NR_BSD43_mpxchan (__NR_BSD43 + 56) +#define __NR_BSD43_symlink (__NR_BSD43 + 57) +#define __NR_BSD43_readlink (__NR_BSD43 + 58) +#define __NR_BSD43_execve (__NR_BSD43 + 59) +#define __NR_BSD43_umask (__NR_BSD43 + 60) +#define __NR_BSD43_chroot (__NR_BSD43 + 61) +#define __NR_BSD43_fstat (__NR_BSD43 + 62) +#define __NR_BSD43_reserved3 (__NR_BSD43 + 63) +#define __NR_BSD43_getpagesize (__NR_BSD43 + 64) +#define __NR_BSD43_mremap (__NR_BSD43 + 65) +#define __NR_BSD43_vfork (__NR_BSD43 + 66) +#define __NR_BSD43_vread (__NR_BSD43 + 67) +#define __NR_BSD43_vwrite (__NR_BSD43 + 68) +#define __NR_BSD43_sbrk (__NR_BSD43 + 69) +#define __NR_BSD43_sstk (__NR_BSD43 + 70) +#define __NR_BSD43_mmap (__NR_BSD43 + 71) +#define __NR_BSD43_vadvise (__NR_BSD43 + 72) +#define __NR_BSD43_munmap (__NR_BSD43 + 73) +#define __NR_BSD43_mprotect (__NR_BSD43 + 74) +#define __NR_BSD43_madvise (__NR_BSD43 + 75) +#define __NR_BSD43_vhangup (__NR_BSD43 + 76) +#define __NR_BSD43_vlimit (__NR_BSD43 + 77) +#define __NR_BSD43_mincore (__NR_BSD43 + 78) +#define __NR_BSD43_getgroups (__NR_BSD43 + 79) +#define __NR_BSD43_setgroups (__NR_BSD43 + 80) +#define __NR_BSD43_getpgrp (__NR_BSD43 + 81) +#define __NR_BSD43_setpgrp (__NR_BSD43 + 82) +#define __NR_BSD43_setitimer (__NR_BSD43 + 83) +#define __NR_BSD43_wait3 (__NR_BSD43 + 84) +#define __NR_BSD43_swapon (__NR_BSD43 + 85) +#define __NR_BSD43_getitimer (__NR_BSD43 + 86) +#define __NR_BSD43_gethostname (__NR_BSD43 + 87) +#define __NR_BSD43_sethostname (__NR_BSD43 + 88) +#define __NR_BSD43_getdtablesize (__NR_BSD43 + 89) +#define __NR_BSD43_dup2 (__NR_BSD43 + 90) +#define __NR_BSD43_getdopt (__NR_BSD43 + 91) +#define __NR_BSD43_fcntl (__NR_BSD43 + 92) +#define __NR_BSD43_select (__NR_BSD43 + 93) +#define __NR_BSD43_setdopt (__NR_BSD43 + 94) +#define __NR_BSD43_fsync (__NR_BSD43 + 95) +#define __NR_BSD43_setpriority (__NR_BSD43 + 96) +#define __NR_BSD43_socket (__NR_BSD43 + 97) +#define __NR_BSD43_connect (__NR_BSD43 + 98) +#define __NR_BSD43_oldaccept (__NR_BSD43 + 99) +#define __NR_BSD43_getpriority (__NR_BSD43 + 100) +#define __NR_BSD43_send (__NR_BSD43 + 101) +#define __NR_BSD43_recv (__NR_BSD43 + 102) +#define __NR_BSD43_sigreturn (__NR_BSD43 + 103) +#define __NR_BSD43_bind (__NR_BSD43 + 104) +#define __NR_BSD43_setsockopt (__NR_BSD43 + 105) +#define __NR_BSD43_listen (__NR_BSD43 + 106) +#define __NR_BSD43_vtimes (__NR_BSD43 + 107) +#define __NR_BSD43_sigvec (__NR_BSD43 + 108) +#define __NR_BSD43_sigblock (__NR_BSD43 + 109) +#define __NR_BSD43_sigsetmask (__NR_BSD43 + 110) +#define __NR_BSD43_sigpause (__NR_BSD43 + 111) +#define __NR_BSD43_sigstack (__NR_BSD43 + 112) +#define __NR_BSD43_oldrecvmsg (__NR_BSD43 + 113) +#define __NR_BSD43_oldsendmsg (__NR_BSD43 + 114) +#define __NR_BSD43_vtrace (__NR_BSD43 + 115) +#define __NR_BSD43_gettimeofday (__NR_BSD43 + 116) +#define __NR_BSD43_getrusage (__NR_BSD43 + 117) +#define __NR_BSD43_getsockopt (__NR_BSD43 + 118) +#define __NR_BSD43_reserved4 (__NR_BSD43 + 119) +#define __NR_BSD43_readv (__NR_BSD43 + 120) +#define __NR_BSD43_writev (__NR_BSD43 + 121) +#define __NR_BSD43_settimeofday (__NR_BSD43 + 122) +#define __NR_BSD43_fchown (__NR_BSD43 + 123) +#define __NR_BSD43_fchmod (__NR_BSD43 + 124) +#define __NR_BSD43_oldrecvfrom (__NR_BSD43 + 125) +#define __NR_BSD43_setreuid (__NR_BSD43 + 126) +#define __NR_BSD43_setregid (__NR_BSD43 + 127) +#define __NR_BSD43_rename (__NR_BSD43 + 128) +#define __NR_BSD43_truncate (__NR_BSD43 + 129) +#define __NR_BSD43_ftruncate (__NR_BSD43 + 130) +#define __NR_BSD43_flock (__NR_BSD43 + 131) +#define __NR_BSD43_semsys (__NR_BSD43 + 132) +#define __NR_BSD43_sendto (__NR_BSD43 + 133) +#define __NR_BSD43_shutdown (__NR_BSD43 + 134) +#define __NR_BSD43_socketpair (__NR_BSD43 + 135) +#define __NR_BSD43_mkdir (__NR_BSD43 + 136) +#define __NR_BSD43_rmdir (__NR_BSD43 + 137) +#define __NR_BSD43_utimes (__NR_BSD43 + 138) +#define __NR_BSD43_sigcleanup (__NR_BSD43 + 139) +#define __NR_BSD43_adjtime (__NR_BSD43 + 140) +#define __NR_BSD43_oldgetpeername (__NR_BSD43 + 141) +#define __NR_BSD43_gethostid (__NR_BSD43 + 142) +#define __NR_BSD43_sethostid (__NR_BSD43 + 143) +#define __NR_BSD43_getrlimit (__NR_BSD43 + 144) +#define __NR_BSD43_setrlimit (__NR_BSD43 + 145) +#define __NR_BSD43_killpg (__NR_BSD43 + 146) +#define __NR_BSD43_shmsys (__NR_BSD43 + 147) +#define __NR_BSD43_quota (__NR_BSD43 + 148) +#define __NR_BSD43_qquota (__NR_BSD43 + 149) +#define __NR_BSD43_oldgetsockname (__NR_BSD43 + 150) +#define __NR_BSD43_sysmips (__NR_BSD43 + 151) +#define __NR_BSD43_cacheflush (__NR_BSD43 + 152) +#define __NR_BSD43_cachectl (__NR_BSD43 + 153) +#define __NR_BSD43_debug (__NR_BSD43 + 154) +#define __NR_BSD43_reserved5 (__NR_BSD43 + 155) +#define __NR_BSD43_reserved6 (__NR_BSD43 + 156) +#define __NR_BSD43_nfs_mount (__NR_BSD43 + 157) +#define __NR_BSD43_nfs_svc (__NR_BSD43 + 158) +#define __NR_BSD43_getdirentries (__NR_BSD43 + 159) +#define __NR_BSD43_statfs (__NR_BSD43 + 160) +#define __NR_BSD43_fstatfs (__NR_BSD43 + 161) +#define __NR_BSD43_unmount (__NR_BSD43 + 162) +#define __NR_BSD43_async_daemon (__NR_BSD43 + 163) +#define __NR_BSD43_nfs_getfh (__NR_BSD43 + 164) +#define __NR_BSD43_getdomainname (__NR_BSD43 + 165) +#define __NR_BSD43_setdomainname (__NR_BSD43 + 166) +#define __NR_BSD43_pcfs_mount (__NR_BSD43 + 167) +#define __NR_BSD43_quotactl (__NR_BSD43 + 168) +#define __NR_BSD43_oldexportfs (__NR_BSD43 + 169) +#define __NR_BSD43_smount (__NR_BSD43 + 170) +#define __NR_BSD43_mipshwconf (__NR_BSD43 + 171) +#define __NR_BSD43_exportfs (__NR_BSD43 + 172) +#define __NR_BSD43_nfsfh_open (__NR_BSD43 + 173) +#define __NR_BSD43_libattach (__NR_BSD43 + 174) +#define __NR_BSD43_libdetach (__NR_BSD43 + 175) +#define __NR_BSD43_accept (__NR_BSD43 + 176) +#define __NR_BSD43_reserved7 (__NR_BSD43 + 177) +#define __NR_BSD43_reserved8 (__NR_BSD43 + 178) +#define __NR_BSD43_recvmsg (__NR_BSD43 + 179) +#define __NR_BSD43_recvfrom (__NR_BSD43 + 180) +#define __NR_BSD43_sendmsg (__NR_BSD43 + 181) +#define __NR_BSD43_getpeername (__NR_BSD43 + 182) +#define __NR_BSD43_getsockname (__NR_BSD43 + 183) +#define __NR_BSD43_aread (__NR_BSD43 + 184) +#define __NR_BSD43_awrite (__NR_BSD43 + 185) +#define __NR_BSD43_listio (__NR_BSD43 + 186) +#define __NR_BSD43_acancel (__NR_BSD43 + 187) +#define __NR_BSD43_astatus (__NR_BSD43 + 188) +#define __NR_BSD43_await (__NR_BSD43 + 189) +#define __NR_BSD43_areadv (__NR_BSD43 + 190) +#define __NR_BSD43_awritev (__NR_BSD43 + 191) + +/* + * POSIX syscalls are in the range from 3000 to 3999 + */ +#define __NR_POSIX 3000 +#define __NR_POSIX_syscall (__NR_POSIX + 0) +#define __NR_POSIX_exit (__NR_POSIX + 1) +#define __NR_POSIX_fork (__NR_POSIX + 2) +#define __NR_POSIX_read (__NR_POSIX + 3) +#define __NR_POSIX_write (__NR_POSIX + 4) +#define __NR_POSIX_open (__NR_POSIX + 5) +#define __NR_POSIX_close (__NR_POSIX + 6) +#define __NR_POSIX_wait (__NR_POSIX + 7) +#define __NR_POSIX_creat (__NR_POSIX + 8) +#define __NR_POSIX_link (__NR_POSIX + 9) +#define __NR_POSIX_unlink (__NR_POSIX + 10) +#define __NR_POSIX_exec (__NR_POSIX + 11) +#define __NR_POSIX_chdir (__NR_POSIX + 12) +#define __NR_POSIX_gtime (__NR_POSIX + 13) +#define __NR_POSIX_mknod (__NR_POSIX + 14) +#define __NR_POSIX_chmod (__NR_POSIX + 15) +#define __NR_POSIX_chown (__NR_POSIX + 16) +#define __NR_POSIX_sbreak (__NR_POSIX + 17) +#define __NR_POSIX_stat (__NR_POSIX + 18) +#define __NR_POSIX_lseek (__NR_POSIX + 19) +#define __NR_POSIX_getpid (__NR_POSIX + 20) +#define __NR_POSIX_mount (__NR_POSIX + 21) +#define __NR_POSIX_umount (__NR_POSIX + 22) +#define __NR_POSIX_setuid (__NR_POSIX + 23) +#define __NR_POSIX_getuid (__NR_POSIX + 24) +#define __NR_POSIX_stime (__NR_POSIX + 25) +#define __NR_POSIX_ptrace (__NR_POSIX + 26) +#define __NR_POSIX_alarm (__NR_POSIX + 27) +#define __NR_POSIX_fstat (__NR_POSIX + 28) +#define __NR_POSIX_pause (__NR_POSIX + 29) +#define __NR_POSIX_utime (__NR_POSIX + 30) +#define __NR_POSIX_stty (__NR_POSIX + 31) +#define __NR_POSIX_gtty (__NR_POSIX + 32) +#define __NR_POSIX_access (__NR_POSIX + 33) +#define __NR_POSIX_nice (__NR_POSIX + 34) +#define __NR_POSIX_statfs (__NR_POSIX + 35) +#define __NR_POSIX_sync (__NR_POSIX + 36) +#define __NR_POSIX_kill (__NR_POSIX + 37) +#define __NR_POSIX_fstatfs (__NR_POSIX + 38) +#define __NR_POSIX_getpgrp (__NR_POSIX + 39) +#define __NR_POSIX_syssgi (__NR_POSIX + 40) +#define __NR_POSIX_dup (__NR_POSIX + 41) +#define __NR_POSIX_pipe (__NR_POSIX + 42) +#define __NR_POSIX_times (__NR_POSIX + 43) +#define __NR_POSIX_profil (__NR_POSIX + 44) +#define __NR_POSIX_lock (__NR_POSIX + 45) +#define __NR_POSIX_setgid (__NR_POSIX + 46) +#define __NR_POSIX_getgid (__NR_POSIX + 47) +#define __NR_POSIX_sig (__NR_POSIX + 48) +#define __NR_POSIX_msgsys (__NR_POSIX + 49) +#define __NR_POSIX_sysmips (__NR_POSIX + 50) +#define __NR_POSIX_sysacct (__NR_POSIX + 51) +#define __NR_POSIX_shmsys (__NR_POSIX + 52) +#define __NR_POSIX_semsys (__NR_POSIX + 53) +#define __NR_POSIX_ioctl (__NR_POSIX + 54) +#define __NR_POSIX_uadmin (__NR_POSIX + 55) +#define __NR_POSIX_exch (__NR_POSIX + 56) +#define __NR_POSIX_utssys (__NR_POSIX + 57) +#define __NR_POSIX_USG_reserved1 (__NR_POSIX + 58) +#define __NR_POSIX_exece (__NR_POSIX + 59) +#define __NR_POSIX_umask (__NR_POSIX + 60) +#define __NR_POSIX_chroot (__NR_POSIX + 61) +#define __NR_POSIX_fcntl (__NR_POSIX + 62) +#define __NR_POSIX_ulimit (__NR_POSIX + 63) +#define __NR_POSIX_SAFARI4_reserved1 (__NR_POSIX + 64) +#define __NR_POSIX_SAFARI4_reserved2 (__NR_POSIX + 65) +#define __NR_POSIX_SAFARI4_reserved3 (__NR_POSIX + 66) +#define __NR_POSIX_SAFARI4_reserved4 (__NR_POSIX + 67) +#define __NR_POSIX_SAFARI4_reserved5 (__NR_POSIX + 68) +#define __NR_POSIX_SAFARI4_reserved6 (__NR_POSIX + 69) +#define __NR_POSIX_advfs (__NR_POSIX + 70) +#define __NR_POSIX_unadvfs (__NR_POSIX + 71) +#define __NR_POSIX_rmount (__NR_POSIX + 72) +#define __NR_POSIX_rumount (__NR_POSIX + 73) +#define __NR_POSIX_rfstart (__NR_POSIX + 74) +#define __NR_POSIX_reserved1 (__NR_POSIX + 75) +#define __NR_POSIX_rdebug (__NR_POSIX + 76) +#define __NR_POSIX_rfstop (__NR_POSIX + 77) +#define __NR_POSIX_rfsys (__NR_POSIX + 78) +#define __NR_POSIX_rmdir (__NR_POSIX + 79) +#define __NR_POSIX_mkdir (__NR_POSIX + 80) +#define __NR_POSIX_getdents (__NR_POSIX + 81) +#define __NR_POSIX_sginap (__NR_POSIX + 82) +#define __NR_POSIX_sgikopt (__NR_POSIX + 83) +#define __NR_POSIX_sysfs (__NR_POSIX + 84) +#define __NR_POSIX_getmsg (__NR_POSIX + 85) +#define __NR_POSIX_putmsg (__NR_POSIX + 86) +#define __NR_POSIX_poll (__NR_POSIX + 87) +#define __NR_POSIX_sigreturn (__NR_POSIX + 88) +#define __NR_POSIX_accept (__NR_POSIX + 89) +#define __NR_POSIX_bind (__NR_POSIX + 90) +#define __NR_POSIX_connect (__NR_POSIX + 91) +#define __NR_POSIX_gethostid (__NR_POSIX + 92) +#define __NR_POSIX_getpeername (__NR_POSIX + 93) +#define __NR_POSIX_getsockname (__NR_POSIX + 94) +#define __NR_POSIX_getsockopt (__NR_POSIX + 95) +#define __NR_POSIX_listen (__NR_POSIX + 96) +#define __NR_POSIX_recv (__NR_POSIX + 97) +#define __NR_POSIX_recvfrom (__NR_POSIX + 98) +#define __NR_POSIX_recvmsg (__NR_POSIX + 99) +#define __NR_POSIX_select (__NR_POSIX + 100) +#define __NR_POSIX_send (__NR_POSIX + 101) +#define __NR_POSIX_sendmsg (__NR_POSIX + 102) +#define __NR_POSIX_sendto (__NR_POSIX + 103) +#define __NR_POSIX_sethostid (__NR_POSIX + 104) +#define __NR_POSIX_setsockopt (__NR_POSIX + 105) +#define __NR_POSIX_shutdown (__NR_POSIX + 106) +#define __NR_POSIX_socket (__NR_POSIX + 107) +#define __NR_POSIX_gethostname (__NR_POSIX + 108) +#define __NR_POSIX_sethostname (__NR_POSIX + 109) +#define __NR_POSIX_getdomainname (__NR_POSIX + 110) +#define __NR_POSIX_setdomainname (__NR_POSIX + 111) +#define __NR_POSIX_truncate (__NR_POSIX + 112) +#define __NR_POSIX_ftruncate (__NR_POSIX + 113) +#define __NR_POSIX_rename (__NR_POSIX + 114) +#define __NR_POSIX_symlink (__NR_POSIX + 115) +#define __NR_POSIX_readlink (__NR_POSIX + 116) +#define __NR_POSIX_lstat (__NR_POSIX + 117) +#define __NR_POSIX_nfs_mount (__NR_POSIX + 118) +#define __NR_POSIX_nfs_svc (__NR_POSIX + 119) +#define __NR_POSIX_nfs_getfh (__NR_POSIX + 120) +#define __NR_POSIX_async_daemon (__NR_POSIX + 121) +#define __NR_POSIX_exportfs (__NR_POSIX + 122) +#define __NR_POSIX_SGI_setregid (__NR_POSIX + 123) +#define __NR_POSIX_SGI_setreuid (__NR_POSIX + 124) +#define __NR_POSIX_getitimer (__NR_POSIX + 125) +#define __NR_POSIX_setitimer (__NR_POSIX + 126) +#define __NR_POSIX_adjtime (__NR_POSIX + 127) +#define __NR_POSIX_SGI_bsdgettime (__NR_POSIX + 128) +#define __NR_POSIX_SGI_sproc (__NR_POSIX + 129) +#define __NR_POSIX_SGI_prctl (__NR_POSIX + 130) +#define __NR_POSIX_SGI_blkproc (__NR_POSIX + 131) +#define __NR_POSIX_SGI_reserved1 (__NR_POSIX + 132) +#define __NR_POSIX_SGI_sgigsc (__NR_POSIX + 133) +#define __NR_POSIX_SGI_mmap (__NR_POSIX + 134) +#define __NR_POSIX_SGI_munmap (__NR_POSIX + 135) +#define __NR_POSIX_SGI_mprotect (__NR_POSIX + 136) +#define __NR_POSIX_SGI_msync (__NR_POSIX + 137) +#define __NR_POSIX_SGI_madvise (__NR_POSIX + 138) +#define __NR_POSIX_SGI_mpin (__NR_POSIX + 139) +#define __NR_POSIX_SGI_getpagesize (__NR_POSIX + 140) +#define __NR_POSIX_SGI_libattach (__NR_POSIX + 141) +#define __NR_POSIX_SGI_libdetach (__NR_POSIX + 142) +#define __NR_POSIX_SGI_getpgrp (__NR_POSIX + 143) +#define __NR_POSIX_SGI_setpgrp (__NR_POSIX + 144) +#define __NR_POSIX_SGI_reserved2 (__NR_POSIX + 145) +#define __NR_POSIX_SGI_reserved3 (__NR_POSIX + 146) +#define __NR_POSIX_SGI_reserved4 (__NR_POSIX + 147) +#define __NR_POSIX_SGI_reserved5 (__NR_POSIX + 148) +#define __NR_POSIX_SGI_reserved6 (__NR_POSIX + 149) +#define __NR_POSIX_cacheflush (__NR_POSIX + 150) +#define __NR_POSIX_cachectl (__NR_POSIX + 151) +#define __NR_POSIX_fchown (__NR_POSIX + 152) +#define __NR_POSIX_fchmod (__NR_POSIX + 153) +#define __NR_POSIX_wait3 (__NR_POSIX + 154) +#define __NR_POSIX_mmap (__NR_POSIX + 155) +#define __NR_POSIX_munmap (__NR_POSIX + 156) +#define __NR_POSIX_madvise (__NR_POSIX + 157) +#define __NR_POSIX_BSD_getpagesize (__NR_POSIX + 158) +#define __NR_POSIX_setreuid (__NR_POSIX + 159) +#define __NR_POSIX_setregid (__NR_POSIX + 160) +#define __NR_POSIX_setpgid (__NR_POSIX + 161) +#define __NR_POSIX_getgroups (__NR_POSIX + 162) +#define __NR_POSIX_setgroups (__NR_POSIX + 163) +#define __NR_POSIX_gettimeofday (__NR_POSIX + 164) +#define __NR_POSIX_getrusage (__NR_POSIX + 165) +#define __NR_POSIX_getrlimit (__NR_POSIX + 166) +#define __NR_POSIX_setrlimit (__NR_POSIX + 167) +#define __NR_POSIX_waitpid (__NR_POSIX + 168) +#define __NR_POSIX_dup2 (__NR_POSIX + 169) +#define __NR_POSIX_reserved2 (__NR_POSIX + 170) +#define __NR_POSIX_reserved3 (__NR_POSIX + 171) +#define __NR_POSIX_reserved4 (__NR_POSIX + 172) +#define __NR_POSIX_reserved5 (__NR_POSIX + 173) +#define __NR_POSIX_reserved6 (__NR_POSIX + 174) +#define __NR_POSIX_reserved7 (__NR_POSIX + 175) +#define __NR_POSIX_reserved8 (__NR_POSIX + 176) +#define __NR_POSIX_reserved9 (__NR_POSIX + 177) +#define __NR_POSIX_reserved10 (__NR_POSIX + 178) +#define __NR_POSIX_reserved11 (__NR_POSIX + 179) +#define __NR_POSIX_reserved12 (__NR_POSIX + 180) +#define __NR_POSIX_reserved13 (__NR_POSIX + 181) +#define __NR_POSIX_reserved14 (__NR_POSIX + 182) +#define __NR_POSIX_reserved15 (__NR_POSIX + 183) +#define __NR_POSIX_reserved16 (__NR_POSIX + 184) +#define __NR_POSIX_reserved17 (__NR_POSIX + 185) +#define __NR_POSIX_reserved18 (__NR_POSIX + 186) +#define __NR_POSIX_reserved19 (__NR_POSIX + 187) +#define __NR_POSIX_reserved20 (__NR_POSIX + 188) +#define __NR_POSIX_reserved21 (__NR_POSIX + 189) +#define __NR_POSIX_reserved22 (__NR_POSIX + 190) +#define __NR_POSIX_reserved23 (__NR_POSIX + 191) +#define __NR_POSIX_reserved24 (__NR_POSIX + 192) +#define __NR_POSIX_reserved25 (__NR_POSIX + 193) +#define __NR_POSIX_reserved26 (__NR_POSIX + 194) +#define __NR_POSIX_reserved27 (__NR_POSIX + 195) +#define __NR_POSIX_reserved28 (__NR_POSIX + 196) +#define __NR_POSIX_reserved29 (__NR_POSIX + 197) +#define __NR_POSIX_reserved30 (__NR_POSIX + 198) +#define __NR_POSIX_reserved31 (__NR_POSIX + 199) +#define __NR_POSIX_reserved32 (__NR_POSIX + 200) +#define __NR_POSIX_reserved33 (__NR_POSIX + 201) +#define __NR_POSIX_reserved34 (__NR_POSIX + 202) +#define __NR_POSIX_reserved35 (__NR_POSIX + 203) +#define __NR_POSIX_reserved36 (__NR_POSIX + 204) +#define __NR_POSIX_reserved37 (__NR_POSIX + 205) +#define __NR_POSIX_reserved38 (__NR_POSIX + 206) +#define __NR_POSIX_reserved39 (__NR_POSIX + 207) +#define __NR_POSIX_reserved40 (__NR_POSIX + 208) +#define __NR_POSIX_reserved41 (__NR_POSIX + 209) +#define __NR_POSIX_reserved42 (__NR_POSIX + 210) +#define __NR_POSIX_reserved43 (__NR_POSIX + 211) +#define __NR_POSIX_reserved44 (__NR_POSIX + 212) +#define __NR_POSIX_reserved45 (__NR_POSIX + 213) +#define __NR_POSIX_reserved46 (__NR_POSIX + 214) +#define __NR_POSIX_reserved47 (__NR_POSIX + 215) +#define __NR_POSIX_reserved48 (__NR_POSIX + 216) +#define __NR_POSIX_reserved49 (__NR_POSIX + 217) +#define __NR_POSIX_reserved50 (__NR_POSIX + 218) +#define __NR_POSIX_reserved51 (__NR_POSIX + 219) +#define __NR_POSIX_reserved52 (__NR_POSIX + 220) +#define __NR_POSIX_reserved53 (__NR_POSIX + 221) +#define __NR_POSIX_reserved54 (__NR_POSIX + 222) +#define __NR_POSIX_reserved55 (__NR_POSIX + 223) +#define __NR_POSIX_reserved56 (__NR_POSIX + 224) +#define __NR_POSIX_reserved57 (__NR_POSIX + 225) +#define __NR_POSIX_reserved58 (__NR_POSIX + 226) +#define __NR_POSIX_reserved59 (__NR_POSIX + 227) +#define __NR_POSIX_reserved60 (__NR_POSIX + 228) +#define __NR_POSIX_reserved61 (__NR_POSIX + 229) +#define __NR_POSIX_reserved62 (__NR_POSIX + 230) +#define __NR_POSIX_reserved63 (__NR_POSIX + 231) +#define __NR_POSIX_reserved64 (__NR_POSIX + 232) +#define __NR_POSIX_reserved65 (__NR_POSIX + 233) +#define __NR_POSIX_reserved66 (__NR_POSIX + 234) +#define __NR_POSIX_reserved67 (__NR_POSIX + 235) +#define __NR_POSIX_reserved68 (__NR_POSIX + 236) +#define __NR_POSIX_reserved69 (__NR_POSIX + 237) +#define __NR_POSIX_reserved70 (__NR_POSIX + 238) +#define __NR_POSIX_reserved71 (__NR_POSIX + 239) +#define __NR_POSIX_reserved72 (__NR_POSIX + 240) +#define __NR_POSIX_reserved73 (__NR_POSIX + 241) +#define __NR_POSIX_reserved74 (__NR_POSIX + 242) +#define __NR_POSIX_reserved75 (__NR_POSIX + 243) +#define __NR_POSIX_reserved76 (__NR_POSIX + 244) +#define __NR_POSIX_reserved77 (__NR_POSIX + 245) +#define __NR_POSIX_reserved78 (__NR_POSIX + 246) +#define __NR_POSIX_reserved79 (__NR_POSIX + 247) +#define __NR_POSIX_reserved80 (__NR_POSIX + 248) +#define __NR_POSIX_reserved81 (__NR_POSIX + 249) +#define __NR_POSIX_reserved82 (__NR_POSIX + 250) +#define __NR_POSIX_reserved83 (__NR_POSIX + 251) +#define __NR_POSIX_reserved84 (__NR_POSIX + 252) +#define __NR_POSIX_reserved85 (__NR_POSIX + 253) +#define __NR_POSIX_reserved86 (__NR_POSIX + 254) +#define __NR_POSIX_reserved87 (__NR_POSIX + 255) +#define __NR_POSIX_reserved88 (__NR_POSIX + 256) +#define __NR_POSIX_reserved89 (__NR_POSIX + 257) +#define __NR_POSIX_reserved90 (__NR_POSIX + 258) +#define __NR_POSIX_reserved91 (__NR_POSIX + 259) +#define __NR_POSIX_netboot (__NR_POSIX + 260) +#define __NR_POSIX_netunboot (__NR_POSIX + 261) +#define __NR_POSIX_rdump (__NR_POSIX + 262) +#define __NR_POSIX_setsid (__NR_POSIX + 263) +#define __NR_POSIX_getmaxsig (__NR_POSIX + 264) +#define __NR_POSIX_sigpending (__NR_POSIX + 265) +#define __NR_POSIX_sigprocmask (__NR_POSIX + 266) +#define __NR_POSIX_sigsuspend (__NR_POSIX + 267) +#define __NR_POSIX_sigaction (__NR_POSIX + 268) +#define __NR_POSIX_MIPS_reserved1 (__NR_POSIX + 269) +#define __NR_POSIX_MIPS_reserved2 (__NR_POSIX + 270) +#define __NR_POSIX_MIPS_reserved3 (__NR_POSIX + 271) +#define __NR_POSIX_MIPS_reserved4 (__NR_POSIX + 272) +#define __NR_POSIX_MIPS_reserved5 (__NR_POSIX + 273) +#define __NR_POSIX_MIPS_reserved6 (__NR_POSIX + 274) +#define __NR_POSIX_MIPS_reserved7 (__NR_POSIX + 275) +#define __NR_POSIX_MIPS_reserved8 (__NR_POSIX + 276) +#define __NR_POSIX_MIPS_reserved9 (__NR_POSIX + 277) +#define __NR_POSIX_MIPS_reserved10 (__NR_POSIX + 278) +#define __NR_POSIX_MIPS_reserved11 (__NR_POSIX + 279) +#define __NR_POSIX_TANDEM_reserved1 (__NR_POSIX + 280) +#define __NR_POSIX_TANDEM_reserved2 (__NR_POSIX + 281) +#define __NR_POSIX_TANDEM_reserved3 (__NR_POSIX + 282) +#define __NR_POSIX_TANDEM_reserved4 (__NR_POSIX + 283) +#define __NR_POSIX_TANDEM_reserved5 (__NR_POSIX + 284) +#define __NR_POSIX_TANDEM_reserved6 (__NR_POSIX + 285) +#define __NR_POSIX_TANDEM_reserved7 (__NR_POSIX + 286) +#define __NR_POSIX_TANDEM_reserved8 (__NR_POSIX + 287) +#define __NR_POSIX_TANDEM_reserved9 (__NR_POSIX + 288) +#define __NR_POSIX_TANDEM_reserved10 (__NR_POSIX + 289) +#define __NR_POSIX_TANDEM_reserved11 (__NR_POSIX + 290) +#define __NR_POSIX_TANDEM_reserved12 (__NR_POSIX + 291) +#define __NR_POSIX_TANDEM_reserved13 (__NR_POSIX + 292) +#define __NR_POSIX_TANDEM_reserved14 (__NR_POSIX + 293) +#define __NR_POSIX_TANDEM_reserved15 (__NR_POSIX + 294) +#define __NR_POSIX_TANDEM_reserved16 (__NR_POSIX + 295) +#define __NR_POSIX_TANDEM_reserved17 (__NR_POSIX + 296) +#define __NR_POSIX_TANDEM_reserved18 (__NR_POSIX + 297) +#define __NR_POSIX_TANDEM_reserved19 (__NR_POSIX + 298) +#define __NR_POSIX_TANDEM_reserved20 (__NR_POSIX + 299) +#define __NR_POSIX_SGI_reserved7 (__NR_POSIX + 300) +#define __NR_POSIX_SGI_reserved8 (__NR_POSIX + 301) +#define __NR_POSIX_SGI_reserved9 (__NR_POSIX + 302) +#define __NR_POSIX_SGI_reserved10 (__NR_POSIX + 303) +#define __NR_POSIX_SGI_reserved11 (__NR_POSIX + 304) +#define __NR_POSIX_SGI_reserved12 (__NR_POSIX + 305) +#define __NR_POSIX_SGI_reserved13 (__NR_POSIX + 306) +#define __NR_POSIX_SGI_reserved14 (__NR_POSIX + 307) +#define __NR_POSIX_SGI_reserved15 (__NR_POSIX + 308) +#define __NR_POSIX_SGI_reserved16 (__NR_POSIX + 309) +#define __NR_POSIX_SGI_reserved17 (__NR_POSIX + 310) +#define __NR_POSIX_SGI_reserved18 (__NR_POSIX + 311) +#define __NR_POSIX_SGI_reserved19 (__NR_POSIX + 312) +#define __NR_POSIX_SGI_reserved20 (__NR_POSIX + 313) +#define __NR_POSIX_SGI_reserved21 (__NR_POSIX + 314) +#define __NR_POSIX_SGI_reserved22 (__NR_POSIX + 315) +#define __NR_POSIX_SGI_reserved23 (__NR_POSIX + 316) +#define __NR_POSIX_SGI_reserved24 (__NR_POSIX + 317) +#define __NR_POSIX_SGI_reserved25 (__NR_POSIX + 318) +#define __NR_POSIX_SGI_reserved26 (__NR_POSIX + 319) + +#endif /* _ASM_RISCOS_SYSCALL_H */ diff --git a/trunk/include/asm-parisc/atomic.h b/trunk/include/asm-parisc/atomic.h index 64ebd086c40d..983e9a2b6042 100644 --- a/trunk/include/asm-parisc/atomic.h +++ b/trunk/include/asm-parisc/atomic.h @@ -216,5 +216,4 @@ static __inline__ int atomic_read(const atomic_t *v) #define smp_mb__before_atomic_inc() smp_mb() #define smp_mb__after_atomic_inc() smp_mb() -#include #endif diff --git a/trunk/include/asm-parisc/mman.h b/trunk/include/asm-parisc/mman.h index 736b0abcac05..e829607eb8bc 100644 --- a/trunk/include/asm-parisc/mman.h +++ b/trunk/include/asm-parisc/mman.h @@ -38,7 +38,6 @@ #define MADV_SPACEAVAIL 5 /* insure that resources are reserved */ #define MADV_VPS_PURGE 6 /* Purge pages from VM page cache */ #define MADV_VPS_INHERIT 7 /* Inherit parents page size */ -#define MADV_REMOVE 8 /* remove these pages & resources */ /* The range 12-64 is reserved for page size specification. */ #define MADV_4K_PAGES 12 /* Use 4K pages */ diff --git a/trunk/include/asm-powerpc/atomic.h b/trunk/include/asm-powerpc/atomic.h index ae395a0632a6..ec4b14468959 100644 --- a/trunk/include/asm-powerpc/atomic.h +++ b/trunk/include/asm-powerpc/atomic.h @@ -402,6 +402,5 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v) #endif /* __powerpc64__ */ -#include #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_ATOMIC_H_ */ diff --git a/trunk/include/asm-powerpc/mman.h b/trunk/include/asm-powerpc/mman.h index a2e34c21b44f..f5e5342fcac5 100644 --- a/trunk/include/asm-powerpc/mman.h +++ b/trunk/include/asm-powerpc/mman.h @@ -44,7 +44,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-ppc/ibm_ocp.h b/trunk/include/asm-ppc/ibm_ocp.h index ddce616f765a..9c21de1ff4ed 100644 --- a/trunk/include/asm-ppc/ibm_ocp.h +++ b/trunk/include/asm-ppc/ibm_ocp.h @@ -63,6 +63,7 @@ struct ocp_func_emac_data { int wol_irq; /* WOL interrupt */ int mdio_idx; /* EMAC idx of MDIO master or -1 */ int tah_idx; /* TAH device index or -1 */ + int jumbo; /* Jumbo frames capable flag */ int phy_mode; /* PHY type or configurable mode */ u8 mac_addr[6]; /* EMAC mac address */ u32 phy_map; /* EMAC phy map */ diff --git a/trunk/include/asm-ppc/io.h b/trunk/include/asm-ppc/io.h index df9cf6ed189d..84ac6e258eef 100644 --- a/trunk/include/asm-ppc/io.h +++ b/trunk/include/asm-ppc/io.h @@ -27,8 +27,6 @@ #if defined(CONFIG_4xx) #include -#elif defined(CONFIG_PPC_MPC52xx) -#include #elif defined(CONFIG_8xx) #include #elif defined(CONFIG_8260) diff --git a/trunk/include/asm-ppc/mpc52xx.h b/trunk/include/asm-ppc/mpc52xx.h index a055e0756b9d..e5f80c22fbfc 100644 --- a/trunk/include/asm-ppc/mpc52xx.h +++ b/trunk/include/asm-ppc/mpc52xx.h @@ -29,17 +29,6 @@ struct pt_regs; #endif /* __ASSEMBLY__ */ -#ifdef CONFIG_PCI -#define _IO_BASE isa_io_base -#define _ISA_MEM_BASE isa_mem_base -#define PCI_DRAM_OFFSET pci_dram_offset -#else -#define _IO_BASE 0 -#define _ISA_MEM_BASE 0 -#define PCI_DRAM_OFFSET 0 -#endif - - /* ======================================================================== */ /* PPC Sys devices definition */ /* ======================================================================== */ @@ -118,7 +107,7 @@ enum ppc_sys_devices { #define MPC52xx_SDMA_IRQ_NUM 17 #define MPC52xx_PERP_IRQ_NUM 23 -#define MPC52xx_CRIT_IRQ_BASE 1 +#define MPC52xx_CRIT_IRQ_BASE 0 #define MPC52xx_MAIN_IRQ_BASE (MPC52xx_CRIT_IRQ_BASE + MPC52xx_CRIT_IRQ_NUM) #define MPC52xx_SDMA_IRQ_BASE (MPC52xx_MAIN_IRQ_BASE + MPC52xx_MAIN_IRQ_NUM) #define MPC52xx_PERP_IRQ_BASE (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM) diff --git a/trunk/include/asm-s390/atomic.h b/trunk/include/asm-s390/atomic.h index d82aedf616fe..b3bd4f679f72 100644 --- a/trunk/include/asm-s390/atomic.h +++ b/trunk/include/asm-s390/atomic.h @@ -5,7 +5,7 @@ * include/asm-s390/atomic.h * * S390 version - * Copyright (C) 1999-2005 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) 1999-2003 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * Denis Joseph Barrow, * Arnd Bergmann (arndb@de.ibm.com) @@ -45,57 +45,59 @@ typedef struct { #define atomic_read(v) ((v)->counter) #define atomic_set(v,i) (((v)->counter) = (i)) +static __inline__ void atomic_add(int i, atomic_t * v) +{ + __CS_LOOP(v, i, "ar"); +} static __inline__ int atomic_add_return(int i, atomic_t * v) { return __CS_LOOP(v, i, "ar"); } -#define atomic_add(_i, _v) atomic_add_return(_i, _v) -#define atomic_add_negative(_i, _v) (atomic_add_return(_i, _v) < 0) -#define atomic_inc(_v) atomic_add_return(1, _v) -#define atomic_inc_return(_v) atomic_add_return(1, _v) -#define atomic_inc_and_test(_v) (atomic_add_return(1, _v) == 0) - +static __inline__ int atomic_add_negative(int i, atomic_t * v) +{ + return __CS_LOOP(v, i, "ar") < 0; +} +static __inline__ void atomic_sub(int i, atomic_t * v) +{ + __CS_LOOP(v, i, "sr"); +} static __inline__ int atomic_sub_return(int i, atomic_t * v) { return __CS_LOOP(v, i, "sr"); } -#define atomic_sub(_i, _v) atomic_sub_return(_i, _v) -#define atomic_sub_and_test(_i, _v) (atomic_sub_return(_i, _v) == 0) -#define atomic_dec(_v) atomic_sub_return(1, _v) -#define atomic_dec_return(_v) atomic_sub_return(1, _v) -#define atomic_dec_and_test(_v) (atomic_sub_return(1, _v) == 0) - -static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t * v) +static __inline__ void atomic_inc(volatile atomic_t * v) { - __CS_LOOP(v, ~mask, "nr"); + __CS_LOOP(v, 1, "ar"); } - -static __inline__ void atomic_set_mask(unsigned long mask, atomic_t * v) +static __inline__ int atomic_inc_return(volatile atomic_t * v) { - __CS_LOOP(v, mask, "or"); + return __CS_LOOP(v, 1, "ar"); } -static __inline__ int atomic_cmpxchg(atomic_t *v, int old, int new) +static __inline__ int atomic_inc_and_test(volatile atomic_t * v) { - __asm__ __volatile__(" cs %0,%3,0(%2)\n" - : "+d" (old), "=m" (v->counter) - : "a" (v), "d" (new), "m" (v->counter) - : "cc", "memory" ); - return old; + return __CS_LOOP(v, 1, "ar") == 0; } - -static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) +static __inline__ void atomic_dec(volatile atomic_t * v) { - int c, old; - - c = atomic_read(v); - while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c) - c = old; - return c != u; + __CS_LOOP(v, 1, "sr"); +} +static __inline__ int atomic_dec_return(volatile atomic_t * v) +{ + return __CS_LOOP(v, 1, "sr"); +} +static __inline__ int atomic_dec_and_test(volatile atomic_t * v) +{ + return __CS_LOOP(v, 1, "sr") == 0; +} +static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t * v) +{ + __CS_LOOP(v, ~mask, "nr"); +} +static __inline__ void atomic_set_mask(unsigned long mask, atomic_t * v) +{ + __CS_LOOP(v, mask, "or"); } - -#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) - #undef __CS_LOOP #ifdef __s390x__ @@ -121,67 +123,97 @@ typedef struct { #define atomic64_read(v) ((v)->counter) #define atomic64_set(v,i) (((v)->counter) = (i)) +static __inline__ void atomic64_add(long long i, atomic64_t * v) +{ + __CSG_LOOP(v, i, "agr"); +} static __inline__ long long atomic64_add_return(long long i, atomic64_t * v) { return __CSG_LOOP(v, i, "agr"); } -#define atomic64_add(_i, _v) atomic64_add_return(_i, _v) -#define atomic64_add_negative(_i, _v) (atomic64_add_return(_i, _v) < 0) -#define atomic64_inc(_v) atomic64_add_return(1, _v) -#define atomic64_inc_return(_v) atomic64_add_return(1, _v) -#define atomic64_inc_and_test(_v) (atomic64_add_return(1, _v) == 0) - -static __inline__ long long atomic64_sub_return(long long i, atomic64_t * v) +static __inline__ long long atomic64_add_negative(long long i, atomic64_t * v) { - return __CSG_LOOP(v, i, "sgr"); + return __CSG_LOOP(v, i, "agr") < 0; +} +static __inline__ void atomic64_sub(long long i, atomic64_t * v) +{ + __CSG_LOOP(v, i, "sgr"); +} +static __inline__ void atomic64_inc(volatile atomic64_t * v) +{ + __CSG_LOOP(v, 1, "agr"); +} +static __inline__ long long atomic64_inc_return(volatile atomic64_t * v) +{ + return __CSG_LOOP(v, 1, "agr"); +} +static __inline__ long long atomic64_inc_and_test(volatile atomic64_t * v) +{ + return __CSG_LOOP(v, 1, "agr") == 0; +} +static __inline__ void atomic64_dec(volatile atomic64_t * v) +{ + __CSG_LOOP(v, 1, "sgr"); +} +static __inline__ long long atomic64_dec_return(volatile atomic64_t * v) +{ + return __CSG_LOOP(v, 1, "sgr"); +} +static __inline__ long long atomic64_dec_and_test(volatile atomic64_t * v) +{ + return __CSG_LOOP(v, 1, "sgr") == 0; } -#define atomic64_sub(_i, _v) atomic64_sub_return(_i, _v) -#define atomic64_sub_and_test(_i, _v) (atomic64_sub_return(_i, _v) == 0) -#define atomic64_dec(_v) atomic64_sub_return(1, _v) -#define atomic64_dec_return(_v) atomic64_sub_return(1, _v) -#define atomic64_dec_and_test(_v) (atomic64_sub_return(1, _v) == 0) - static __inline__ void atomic64_clear_mask(unsigned long mask, atomic64_t * v) { __CSG_LOOP(v, ~mask, "ngr"); } - static __inline__ void atomic64_set_mask(unsigned long mask, atomic64_t * v) { __CSG_LOOP(v, mask, "ogr"); } -static __inline__ long long atomic64_cmpxchg(atomic64_t *v, - long long old, long long new) -{ - __asm__ __volatile__(" csg %0,%3,0(%2)\n" - : "+d" (old), "=m" (v->counter) - : "a" (v), "d" (new), "m" (v->counter) - : "cc", "memory" ); - return old; -} +#undef __CSG_LOOP +#endif -static __inline__ int atomic64_add_unless(atomic64_t *v, - long long a, long long u) -{ - long long c, old; +/* + returns 0 if expected_oldval==value in *v ( swap was successful ) + returns 1 if unsuccessful. - c = atomic64_read(v); - while (c != u && (old = atomic64_cmpxchg(v, c, c + a)) != c) - c = old; - return c != u; + This is non-portable, use bitops or spinlocks instead! +*/ +static __inline__ int +atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v) +{ + int retval; + + __asm__ __volatile__( + " lr %0,%3\n" + " cs %0,%4,0(%2)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "=m" (v->counter) + : "a" (v), "d" (expected_oldval) , "d" (new_val), + "m" (v->counter) : "cc", "memory" ); + return retval; } -#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) +#define atomic_cmpxchg(v, o, n) (atomic_compare_and_swap((o), (n), &((v)->counter))) -#undef __CSG_LOOP -#endif +#define atomic_add_unless(v, a, u) \ +({ \ + int c, old; \ + c = atomic_read(v); \ + while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ + c = old; \ + c != (u); \ +}) +#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) #define smp_mb__before_atomic_dec() smp_mb() #define smp_mb__after_atomic_dec() smp_mb() #define smp_mb__before_atomic_inc() smp_mb() #define smp_mb__after_atomic_inc() smp_mb() -#include #endif /* __KERNEL__ */ #endif /* __ARCH_S390_ATOMIC__ */ diff --git a/trunk/include/asm-s390/ccwdev.h b/trunk/include/asm-s390/ccwdev.h index 12456cb2f882..3eb231af5d51 100644 --- a/trunk/include/asm-s390/ccwdev.h +++ b/trunk/include/asm-s390/ccwdev.h @@ -185,5 +185,8 @@ extern struct ccw_device *ccw_device_probe_console(void); extern int _ccw_device_get_device_number(struct ccw_device *); extern int _ccw_device_get_subchannel_number(struct ccw_device *); +extern struct device *s390_root_dev_register(const char *); +extern void s390_root_dev_unregister(struct device *); + extern void *ccw_device_get_chp_desc(struct ccw_device *, int); #endif /* _S390_CCWDEV_H_ */ diff --git a/trunk/include/asm-s390/mman.h b/trunk/include/asm-s390/mman.h index c8d5409b5d56..ea86bd12204f 100644 --- a/trunk/include/asm-s390/mman.h +++ b/trunk/include/asm-s390/mman.h @@ -43,7 +43,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-s390/qdio.h b/trunk/include/asm-s390/qdio.h index 7bc15f0231db..0ddf0a8ef8de 100644 --- a/trunk/include/asm-s390/qdio.h +++ b/trunk/include/asm-s390/qdio.h @@ -195,14 +195,12 @@ struct qdr { /* * queue information block (QIB) */ -#define QIB_AC_INBOUND_PCI_SUPPORTED 0x80 -#define QIB_AC_OUTBOUND_PCI_SUPPORTED 0x40 -#define QIB_RFLAGS_ENABLE_QEBSM 0x80 - +#define QIB_AC_INBOUND_PCI_SUPPORTED 0x80 +#define QIB_AC_OUTBOUND_PCI_SUPPORTED 0x40 struct qib { unsigned int qfmt : 8; /* queue format */ unsigned int pfmt : 8; /* impl. dep. parameter format */ - unsigned int rflags : 8; /* QEBSM */ + unsigned int res1 : 8; /* reserved */ unsigned int ac : 8; /* adapter characteristics */ unsigned int res2; /* reserved */ #ifdef QDIO_32_BIT diff --git a/trunk/include/asm-s390/s390_rdev.h b/trunk/include/asm-s390/s390_rdev.h deleted file mode 100644 index 3ad78f2b9c48..000000000000 --- a/trunk/include/asm-s390/s390_rdev.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * include/asm-s390/ccwdev.h - * - * Copyright (C) 2002,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Cornelia Huck - * Carsten Otte - * - * Interface for s390 root device - */ - -#ifndef _S390_RDEV_H_ -#define _S390_RDEV_H_ -extern struct device *s390_root_dev_register(const char *); -extern void s390_root_dev_unregister(struct device *); -#endif /* _S390_RDEV_H_ */ diff --git a/trunk/include/asm-s390/uaccess.h b/trunk/include/asm-s390/uaccess.h index be104f21c70a..10a619da4761 100644 --- a/trunk/include/asm-s390/uaccess.h +++ b/trunk/include/asm-s390/uaccess.h @@ -61,10 +61,8 @@ #define segment_eq(a,b) ((a).ar4 == (b).ar4) -static inline int __access_ok(const void *addr, unsigned long size) -{ - return 1; -} +#define __access_ok(addr,size) (1) + #define access_ok(type,addr,size) __access_ok(addr,size) /* @@ -208,25 +206,25 @@ extern int __put_user_bad(void) __attribute__((noreturn)); case 1: { \ unsigned char __x; \ __get_user_asm(__x, ptr, __gu_err); \ - (x) = *(__typeof__(*(ptr)) *) &__x; \ + (x) = (__typeof__(*(ptr))) __x; \ break; \ }; \ case 2: { \ unsigned short __x; \ __get_user_asm(__x, ptr, __gu_err); \ - (x) = *(__typeof__(*(ptr)) *) &__x; \ + (x) = (__typeof__(*(ptr))) __x; \ break; \ }; \ case 4: { \ unsigned int __x; \ __get_user_asm(__x, ptr, __gu_err); \ - (x) = *(__typeof__(*(ptr)) *) &__x; \ + (x) = (__typeof__(*(ptr))) __x; \ break; \ }; \ case 8: { \ unsigned long long __x; \ __get_user_asm(__x, ptr, __gu_err); \ - (x) = *(__typeof__(*(ptr)) *) &__x; \ + (x) = (__typeof__(*(ptr))) __x; \ break; \ }; \ default: \ diff --git a/trunk/include/asm-s390/unistd.h b/trunk/include/asm-s390/unistd.h index 2861cdc243ad..f97d92691f17 100644 --- a/trunk/include/asm-s390/unistd.h +++ b/trunk/include/asm-s390/unistd.h @@ -539,7 +539,7 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ #define __ARCH_WANT_SYS_SIGPENDING #define __ARCH_WANT_SYS_SIGPROCMASK #define __ARCH_WANT_SYS_RT_SIGACTION -# ifndef CONFIG_64BIT +# ifdef CONFIG_ARCH_S390_31 # define __ARCH_WANT_STAT64 # define __ARCH_WANT_SYS_TIME # endif diff --git a/trunk/include/asm-s390/vtoc.h b/trunk/include/asm-s390/vtoc.h index d1de5b7ebb0b..41d369f38b0e 100644 --- a/trunk/include/asm-s390/vtoc.h +++ b/trunk/include/asm-s390/vtoc.h @@ -176,28 +176,4 @@ struct vtoc_format7_label struct vtoc_cchhb DS7PTRDS; /* pointer to next FMT7 DSCB */ } __attribute__ ((packed)); -struct vtoc_cms_label { - u8 label_id[4]; /* Label identifier */ - u8 vol_id[6]; /* Volid */ - u16 version_id; /* Version identifier */ - u32 block_size; /* Disk block size */ - u32 origin_ptr; /* Disk origin pointer */ - u32 usable_count; /* Number of usable cylinders/blocks */ - u32 formatted_count; /* Maximum number of formatted cylinders/ - * blocks */ - u32 block_count; /* Disk size in CMS blocks */ - u32 used_count; /* Number of CMS blocks in use */ - u32 fst_size; /* File Status Table (FST) size */ - u32 fst_count; /* Number of FSTs per CMS block */ - u8 format_date[6]; /* Disk FORMAT date */ - u8 reserved1[2]; - u32 disk_offset; /* Disk offset when reserved*/ - u32 map_block; /* Allocation Map Block with next hole */ - u32 hblk_disp; /* Displacement into HBLK data of next hole */ - u32 user_disp; /* Displacement into user part of Allocation - * map */ - u8 reserved2[4]; - u8 segment_name[8]; /* Name of shared segment */ -} __attribute__ ((packed)); - #endif /* _ASM_S390_VTOC_H */ diff --git a/trunk/include/asm-sh/atomic.h b/trunk/include/asm-sh/atomic.h index 618d8e0de348..aabfd334462c 100644 --- a/trunk/include/asm-sh/atomic.h +++ b/trunk/include/asm-sh/atomic.h @@ -140,5 +140,4 @@ static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif /* __ASM_SH_ATOMIC_H */ diff --git a/trunk/include/asm-sh/mman.h b/trunk/include/asm-sh/mman.h index 693bd55a3710..3ebab5f79db7 100644 --- a/trunk/include/asm-sh/mman.h +++ b/trunk/include/asm-sh/mman.h @@ -35,7 +35,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-sh64/atomic.h b/trunk/include/asm-sh64/atomic.h index f3ce5c0df13a..927a2bc27b30 100644 --- a/trunk/include/asm-sh64/atomic.h +++ b/trunk/include/asm-sh64/atomic.h @@ -152,5 +152,4 @@ static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif /* __ASM_SH64_ATOMIC_H */ diff --git a/trunk/include/asm-sparc/atomic.h b/trunk/include/asm-sparc/atomic.h index accb4967e9d2..62bec7ad271c 100644 --- a/trunk/include/asm-sparc/atomic.h +++ b/trunk/include/asm-sparc/atomic.h @@ -159,5 +159,4 @@ static inline int __atomic24_sub(int i, atomic24_t *v) #endif /* !(__KERNEL__) */ -#include #endif /* !(__ARCH_SPARC_ATOMIC__) */ diff --git a/trunk/include/asm-sparc/mman.h b/trunk/include/asm-sparc/mman.h index 98435ad8619e..138eb81dd70d 100644 --- a/trunk/include/asm-sparc/mman.h +++ b/trunk/include/asm-sparc/mman.h @@ -54,7 +54,6 @@ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ #define MADV_FREE 0x5 /* (Solaris) contents can be freed */ -#define MADV_REMOVE 0x6 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-sparc64/atomic.h b/trunk/include/asm-sparc64/atomic.h index 11f5aa5d108c..3789fe315992 100644 --- a/trunk/include/asm-sparc64/atomic.h +++ b/trunk/include/asm-sparc64/atomic.h @@ -96,5 +96,4 @@ extern int atomic64_sub_ret(int, atomic64_t *); #define smp_mb__after_atomic_inc() barrier() #endif -#include #endif /* !(__ARCH_SPARC64_ATOMIC__) */ diff --git a/trunk/include/asm-sparc64/mman.h b/trunk/include/asm-sparc64/mman.h index cb4b6156194d..01cecf54357b 100644 --- a/trunk/include/asm-sparc64/mman.h +++ b/trunk/include/asm-sparc64/mman.h @@ -54,7 +54,6 @@ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ #define MADV_FREE 0x5 /* (Solaris) contents can be freed */ -#define MADV_REMOVE 0x6 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-v850/atomic.h b/trunk/include/asm-v850/atomic.h index f5b9ab6f4e70..bede3172ce7f 100644 --- a/trunk/include/asm-v850/atomic.h +++ b/trunk/include/asm-v850/atomic.h @@ -126,5 +126,4 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif /* __V850_ATOMIC_H__ */ diff --git a/trunk/include/asm-v850/mman.h b/trunk/include/asm-v850/mman.h index edc79965193a..e2b90081b56f 100644 --- a/trunk/include/asm-v850/mman.h +++ b/trunk/include/asm-v850/mman.h @@ -32,7 +32,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-x86_64/atomic.h b/trunk/include/asm-x86_64/atomic.h index 72eb071488c7..50db9f39274f 100644 --- a/trunk/include/asm-x86_64/atomic.h +++ b/trunk/include/asm-x86_64/atomic.h @@ -424,5 +424,4 @@ __asm__ __volatile__(LOCK "orl %0,%1" \ #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif diff --git a/trunk/include/asm-x86_64/cacheflush.h b/trunk/include/asm-x86_64/cacheflush.h index d32f7f58752a..b3189fb229d1 100644 --- a/trunk/include/asm-x86_64/cacheflush.h +++ b/trunk/include/asm-x86_64/cacheflush.h @@ -27,8 +27,4 @@ void global_flush_tlb(void); int change_page_attr(struct page *page, int numpages, pgprot_t prot); int change_page_attr_addr(unsigned long addr, int numpages, pgprot_t prot); -#ifdef CONFIG_DEBUG_RODATA -void mark_rodata_ro(void); -#endif - #endif /* _X8664_CACHEFLUSH_H */ diff --git a/trunk/include/asm-x86_64/mman.h b/trunk/include/asm-x86_64/mman.h index d0e97b74f735..78e60a4fd4ee 100644 --- a/trunk/include/asm-x86_64/mman.h +++ b/trunk/include/asm-x86_64/mman.h @@ -36,7 +36,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/asm-x86_64/mpspec.h b/trunk/include/asm-x86_64/mpspec.h index 10248a9a0582..6f8a17d105ab 100644 --- a/trunk/include/asm-x86_64/mpspec.h +++ b/trunk/include/asm-x86_64/mpspec.h @@ -76,7 +76,7 @@ struct mpc_config_bus { unsigned char mpc_type; unsigned char mpc_busid; - unsigned char mpc_bustype[6]; + unsigned char mpc_bustype[6] __attribute((packed)); }; /* List of Bus Type string values, Intel MP Spec. */ diff --git a/trunk/include/asm-x86_64/pgtable.h b/trunk/include/asm-x86_64/pgtable.h index 02888d7a496f..ecf58c7c1650 100644 --- a/trunk/include/asm-x86_64/pgtable.h +++ b/trunk/include/asm-x86_64/pgtable.h @@ -122,8 +122,6 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long #define pte_same(a, b) ((a).pte == (b).pte) -#define pte_pgprot(a) (__pgprot((a).pte & ~PHYSICAL_PAGE_MASK)) - #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) #define PUD_SIZE (1UL << PUD_SHIFT) diff --git a/trunk/include/asm-x86_64/system.h b/trunk/include/asm-x86_64/system.h index b34cc2ee222b..85348e02ad2e 100644 --- a/trunk/include/asm-x86_64/system.h +++ b/trunk/include/asm-x86_64/system.h @@ -315,8 +315,6 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, #define local_irq_enable() __asm__ __volatile__("sti": : :"memory") /* used in the idle loop; sti takes one instruction cycle to complete */ #define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory") -/* used when interrupts are already enabled or to shutdown the processor */ -#define halt() __asm__ __volatile__("hlt": : :"memory") #define irqs_disabled() \ ({ \ diff --git a/trunk/include/asm-xtensa/atomic.h b/trunk/include/asm-xtensa/atomic.h index e2ce06b101ad..3670cc7695da 100644 --- a/trunk/include/asm-xtensa/atomic.h +++ b/trunk/include/asm-xtensa/atomic.h @@ -286,7 +286,6 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v) #define smp_mb__before_atomic_inc() barrier() #define smp_mb__after_atomic_inc() barrier() -#include #endif /* __KERNEL__ */ #endif /* _XTENSA_ATOMIC_H */ diff --git a/trunk/include/asm-xtensa/mman.h b/trunk/include/asm-xtensa/mman.h index 082a7504925e..9a95a45df996 100644 --- a/trunk/include/asm-xtensa/mman.h +++ b/trunk/include/asm-xtensa/mman.h @@ -72,7 +72,6 @@ #define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */ #define MADV_WILLNEED 0x3 /* pre-fault pages */ #define MADV_DONTNEED 0x4 /* discard these pages */ -#define MADV_REMOVE 0x5 /* remove these pages & resources */ /* compatibility flags */ #define MAP_ANON MAP_ANONYMOUS diff --git a/trunk/include/keys/user-type.h b/trunk/include/keys/user-type.h index a3dae1803f45..26f6ec38577a 100644 --- a/trunk/include/keys/user-type.h +++ b/trunk/include/keys/user-type.h @@ -35,6 +35,7 @@ struct user_key_payload { extern struct key_type key_type_user; extern int user_instantiate(struct key *key, const void *data, size_t datalen); +extern int user_duplicate(struct key *key, const struct key *source); extern int user_update(struct key *key, const void *data, size_t datalen); extern int user_match(const struct key *key, const void *criterion); extern void user_destroy(struct key *key); diff --git a/trunk/include/linux/ata.h b/trunk/include/linux/ata.h index 94f77cce27fa..d2873b732bb1 100644 --- a/trunk/include/linux/ata.h +++ b/trunk/include/linux/ata.h @@ -129,7 +129,6 @@ enum { ATA_CMD_READ_EXT = 0x25, ATA_CMD_WRITE = 0xCA, ATA_CMD_WRITE_EXT = 0x35, - ATA_CMD_WRITE_FUA_EXT = 0x3D, ATA_CMD_PIO_READ = 0x20, ATA_CMD_PIO_READ_EXT = 0x24, ATA_CMD_PIO_WRITE = 0x30, @@ -138,13 +137,10 @@ enum { ATA_CMD_READ_MULTI_EXT = 0x29, ATA_CMD_WRITE_MULTI = 0xC5, ATA_CMD_WRITE_MULTI_EXT = 0x39, - ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE, ATA_CMD_SET_FEATURES = 0xEF, ATA_CMD_PACKET = 0xA0, ATA_CMD_VERIFY = 0x40, ATA_CMD_VERIFY_EXT = 0x42, - ATA_CMD_STANDBYNOW1 = 0xE0, - ATA_CMD_IDLEIMMEDIATE = 0xE1, ATA_CMD_INIT_DEV_PARAMS = 0x91, /* SETFEATURES stuff */ @@ -196,7 +192,6 @@ enum { ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ - ATA_TFLAG_FUA = (1 << 5), /* enable FUA */ }; enum ata_tf_protocols { @@ -250,8 +245,7 @@ struct ata_taskfile { #define ata_id_is_sata(id) ((id)[93] == 0) #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) -#define ata_id_has_fua(id) ((id)[84] & (1 << 6)) -#define ata_id_has_flush(id) ((id)[83] & (1 << 12)) +#define ata_id_has_flush(id) ((id)[83] & (1 << 12)) #define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13)) #define ata_id_has_lba48(id) ((id)[83] & (1 << 10)) #define ata_id_has_wcache(id) ((id)[82] & (1 << 5)) diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index fb0985377421..a18500d196e1 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -102,7 +102,7 @@ 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; -typedef void (rq_end_io_fn)(struct request *, int); +typedef void (rq_end_io_fn)(struct request *); struct request_list { int count[2]; @@ -207,7 +207,6 @@ enum rq_flag_bits { __REQ_SORTED, /* elevator knows about this request */ __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ __REQ_HARDBARRIER, /* may not be passed by drive either */ - __REQ_FUA, /* forced unit access */ __REQ_CMD, /* is a regular fs rw request */ __REQ_NOMERGE, /* don't touch this for merging */ __REQ_STARTED, /* drive already may have started this one */ @@ -231,7 +230,9 @@ enum rq_flag_bits { __REQ_PM_SUSPEND, /* suspend request */ __REQ_PM_RESUME, /* resume request */ __REQ_PM_SHUTDOWN, /* shutdown request */ - __REQ_ORDERED_COLOR, /* is before or after barrier */ + __REQ_BAR_PREFLUSH, /* barrier pre-flush done */ + __REQ_BAR_POSTFLUSH, /* barrier post-flush */ + __REQ_BAR_FLUSH, /* rq is the flush request */ __REQ_NR_BITS, /* stops here */ }; @@ -240,7 +241,6 @@ enum rq_flag_bits { #define REQ_SORTED (1 << __REQ_SORTED) #define REQ_SOFTBARRIER (1 << __REQ_SOFTBARRIER) #define REQ_HARDBARRIER (1 << __REQ_HARDBARRIER) -#define REQ_FUA (1 << __REQ_FUA) #define REQ_CMD (1 << __REQ_CMD) #define REQ_NOMERGE (1 << __REQ_NOMERGE) #define REQ_STARTED (1 << __REQ_STARTED) @@ -260,7 +260,9 @@ enum rq_flag_bits { #define REQ_PM_SUSPEND (1 << __REQ_PM_SUSPEND) #define REQ_PM_RESUME (1 << __REQ_PM_RESUME) #define REQ_PM_SHUTDOWN (1 << __REQ_PM_SHUTDOWN) -#define REQ_ORDERED_COLOR (1 << __REQ_ORDERED_COLOR) +#define REQ_BAR_PREFLUSH (1 << __REQ_BAR_PREFLUSH) +#define REQ_BAR_POSTFLUSH (1 << __REQ_BAR_POSTFLUSH) +#define REQ_BAR_FLUSH (1 << __REQ_BAR_FLUSH) /* * State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME @@ -290,7 +292,8 @@ struct bio_vec; typedef int (merge_bvec_fn) (request_queue_t *, struct bio *, struct bio_vec *); typedef void (activity_fn) (void *data, int rw); typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *); -typedef void (prepare_flush_fn) (request_queue_t *, struct request *); +typedef int (prepare_flush_fn) (request_queue_t *, struct request *); +typedef void (end_flush_fn) (request_queue_t *, struct request *); enum blk_queue_state { Queue_down, @@ -332,6 +335,7 @@ struct request_queue activity_fn *activity_fn; issue_flush_fn *issue_flush_fn; prepare_flush_fn *prepare_flush_fn; + end_flush_fn *end_flush_fn; /* * Dispatch queue sorting @@ -416,11 +420,14 @@ struct request_queue /* * reserved for flush operations */ - unsigned int ordered, next_ordered, ordseq; - int orderr, ordcolor; - struct request pre_flush_rq, bar_rq, post_flush_rq; - struct request *orig_bar_rq; - unsigned int bi_size; + struct request *flush_rq; + unsigned char ordered; +}; + +enum { + QUEUE_ORDERED_NONE, + QUEUE_ORDERED_TAG, + QUEUE_ORDERED_FLUSH, }; #define RQ_INACTIVE (-1) @@ -438,51 +445,12 @@ struct request_queue #define QUEUE_FLAG_REENTER 6 /* Re-entrancy avoidance */ #define QUEUE_FLAG_PLUGGED 7 /* queue is plugged */ #define QUEUE_FLAG_ELVSWITCH 8 /* don't use elevator, just do FIFO */ - -enum { - /* - * Hardbarrier is supported with one of the following methods. - * - * NONE : hardbarrier unsupported - * DRAIN : ordering by draining is enough - * DRAIN_FLUSH : ordering by draining w/ pre and post flushes - * DRAIN_FUA : ordering by draining w/ pre flush and FUA write - * TAG : ordering by tag is enough - * TAG_FLUSH : ordering by tag w/ pre and post flushes - * TAG_FUA : ordering by tag w/ pre flush and FUA write - */ - QUEUE_ORDERED_NONE = 0x00, - QUEUE_ORDERED_DRAIN = 0x01, - QUEUE_ORDERED_TAG = 0x02, - - QUEUE_ORDERED_PREFLUSH = 0x10, - QUEUE_ORDERED_POSTFLUSH = 0x20, - QUEUE_ORDERED_FUA = 0x40, - - QUEUE_ORDERED_DRAIN_FLUSH = QUEUE_ORDERED_DRAIN | - QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH, - QUEUE_ORDERED_DRAIN_FUA = QUEUE_ORDERED_DRAIN | - QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_FUA, - QUEUE_ORDERED_TAG_FLUSH = QUEUE_ORDERED_TAG | - QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_POSTFLUSH, - QUEUE_ORDERED_TAG_FUA = QUEUE_ORDERED_TAG | - QUEUE_ORDERED_PREFLUSH | QUEUE_ORDERED_FUA, - - /* - * Ordered operation sequence - */ - QUEUE_ORDSEQ_STARTED = 0x01, /* flushing in progress */ - QUEUE_ORDSEQ_DRAIN = 0x02, /* waiting for the queue to be drained */ - QUEUE_ORDSEQ_PREFLUSH = 0x04, /* pre-flushing in progress */ - QUEUE_ORDSEQ_BAR = 0x08, /* original barrier req in progress */ - QUEUE_ORDSEQ_POSTFLUSH = 0x10, /* post-flushing in progress */ - QUEUE_ORDSEQ_DONE = 0x20, -}; +#define QUEUE_FLAG_FLUSH 9 /* doing barrier flush sequence */ #define blk_queue_plugged(q) test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags) #define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags) #define blk_queue_stopped(q) test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags) -#define blk_queue_flushing(q) ((q)->ordseq) +#define blk_queue_flushing(q) test_bit(QUEUE_FLAG_FLUSH, &(q)->queue_flags) #define blk_fs_request(rq) ((rq)->flags & REQ_CMD) #define blk_pc_request(rq) ((rq)->flags & REQ_BLOCK_PC) @@ -498,7 +466,8 @@ enum { #define blk_sorted_rq(rq) ((rq)->flags & REQ_SORTED) #define blk_barrier_rq(rq) ((rq)->flags & REQ_HARDBARRIER) -#define blk_fua_rq(rq) ((rq)->flags & REQ_FUA) +#define blk_barrier_preflush(rq) ((rq)->flags & REQ_BAR_PREFLUSH) +#define blk_barrier_postflush(rq) ((rq)->flags & REQ_BAR_POSTFLUSH) #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) @@ -591,7 +560,7 @@ extern void register_disk(struct gendisk *dev); extern void generic_make_request(struct bio *bio); extern void blk_put_request(struct request *); extern void __blk_put_request(request_queue_t *, struct request *); -extern void blk_end_sync_rq(struct request *rq, int error); +extern void blk_end_sync_rq(struct request *rq); extern void blk_attempt_remerge(request_queue_t *, struct request *); extern struct request *blk_get_request(request_queue_t *, int, gfp_t); extern void blk_insert_request(request_queue_t *, struct request *, int, void *); @@ -613,7 +582,8 @@ extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_io extern int blk_execute_rq(request_queue_t *, struct gendisk *, struct request *, int); extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *, - struct request *, int, rq_end_io_fn *); + struct request *, int, + void (*done)(struct request *)); static inline request_queue_t *bdev_get_queue(struct block_device *bdev) { @@ -644,7 +614,7 @@ static inline void blk_run_address_space(struct address_space *mapping) */ extern int end_that_request_first(struct request *, int, int); extern int end_that_request_chunk(struct request *, int, int); -extern void end_that_request_last(struct request *, int); +extern void end_that_request_last(struct request *); extern void end_request(struct request *req, int uptodate); /* @@ -695,12 +665,11 @@ extern void blk_queue_prep_rq(request_queue_t *, prep_rq_fn *pfn); extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *); extern void blk_queue_dma_alignment(request_queue_t *, int); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); -extern int blk_queue_ordered(request_queue_t *, unsigned, prepare_flush_fn *); +extern void blk_queue_ordered(request_queue_t *, int); extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *); -extern int blk_do_ordered(request_queue_t *, struct request **); -extern unsigned blk_ordered_cur_seq(request_queue_t *); -extern unsigned blk_ordered_req_seq(struct request *); -extern void blk_ordered_complete_seq(request_queue_t *, unsigned, int); +extern struct request *blk_start_pre_flush(request_queue_t *,struct request *); +extern int blk_complete_barrier_rq(request_queue_t *, struct request *, int); +extern int blk_complete_barrier_rq_locked(request_queue_t *, struct request *, int); extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *); extern void blk_dump_rq_flags(struct request *, char *); diff --git a/trunk/include/linux/bootmem.h b/trunk/include/linux/bootmem.h index 993da8cc9706..3b03b0b868dd 100644 --- a/trunk/include/linux/bootmem.h +++ b/trunk/include/linux/bootmem.h @@ -43,38 +43,50 @@ typedef struct bootmem_data { extern unsigned long __init bootmem_bootmap_pages (unsigned long); extern unsigned long __init init_bootmem (unsigned long addr, unsigned long memend); extern void __init free_bootmem (unsigned long addr, unsigned long size); -extern void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal); -extern void * __init __alloc_bootmem_low(unsigned long size, - unsigned long align, - unsigned long goal); -extern void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, - unsigned long size, - unsigned long align, - unsigned long goal); +extern void * __init __alloc_bootmem_limit (unsigned long size, unsigned long align, unsigned long goal, unsigned long limit); #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE extern void __init reserve_bootmem (unsigned long addr, unsigned long size); #define alloc_bootmem(x) \ __alloc_bootmem((x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_low(x) \ - __alloc_bootmem_low((x), SMP_CACHE_BYTES, 0) + __alloc_bootmem((x), SMP_CACHE_BYTES, 0) #define alloc_bootmem_pages(x) \ __alloc_bootmem((x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_low_pages(x) \ - __alloc_bootmem_low((x), PAGE_SIZE, 0) + __alloc_bootmem((x), PAGE_SIZE, 0) + +#define alloc_bootmem_limit(x, limit) \ + __alloc_bootmem_limit((x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS), (limit)) +#define alloc_bootmem_low_limit(x, limit) \ + __alloc_bootmem_limit((x), SMP_CACHE_BYTES, 0, (limit)) +#define alloc_bootmem_pages_limit(x, limit) \ + __alloc_bootmem_limit((x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS), (limit)) +#define alloc_bootmem_low_pages_limit(x, limit) \ + __alloc_bootmem_limit((x), PAGE_SIZE, 0, (limit)) + #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ extern unsigned long __init free_all_bootmem (void); -extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal); + extern unsigned long __init init_bootmem_node (pg_data_t *pgdat, unsigned long freepfn, unsigned long startpfn, unsigned long endpfn); extern void __init reserve_bootmem_node (pg_data_t *pgdat, unsigned long physaddr, unsigned long size); extern void __init free_bootmem_node (pg_data_t *pgdat, unsigned long addr, unsigned long size); extern unsigned long __init free_all_bootmem_node (pg_data_t *pgdat); +extern void * __init __alloc_bootmem_node_limit (pg_data_t *pgdat, unsigned long size, unsigned long align, unsigned long goal, unsigned long limit); #ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE #define alloc_bootmem_node(pgdat, x) \ __alloc_bootmem_node((pgdat), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_pages_node(pgdat, x) \ __alloc_bootmem_node((pgdat), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS)) #define alloc_bootmem_low_pages_node(pgdat, x) \ - __alloc_bootmem_low_node((pgdat), (x), PAGE_SIZE, 0) + __alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0) + +#define alloc_bootmem_node_limit(pgdat, x, limit) \ + __alloc_bootmem_node_limit((pgdat), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS), (limit)) +#define alloc_bootmem_pages_node_limit(pgdat, x, limit) \ + __alloc_bootmem_node_limit((pgdat), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS), (limit)) +#define alloc_bootmem_low_pages_node_limit(pgdat, x, limit) \ + __alloc_bootmem_node_limit((pgdat), (x), PAGE_SIZE, 0, (limit)) + #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */ #ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP @@ -111,5 +123,15 @@ extern void *__init alloc_large_system_hash(const char *tablename, #endif extern int __initdata hashdist; /* Distribute hashes across NUMA nodes? */ +static inline void *__alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal) +{ + return __alloc_bootmem_limit(size, align, goal, 0); +} + +static inline void *__alloc_bootmem_node (pg_data_t *pgdat, unsigned long size, unsigned long align, + unsigned long goal) +{ + return __alloc_bootmem_node_limit(pgdat, size, align, goal, 0); +} #endif /* _LINUX_BOOTMEM_H */ diff --git a/trunk/include/linux/dm-ioctl.h b/trunk/include/linux/dm-ioctl.h index fa75ba0d635e..f5eb6b6cd109 100644 --- a/trunk/include/linux/dm-ioctl.h +++ b/trunk/include/linux/dm-ioctl.h @@ -272,9 +272,9 @@ typedef char ioctl_struct[308]; #define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl) #define DM_VERSION_MAJOR 4 -#define DM_VERSION_MINOR 5 +#define DM_VERSION_MINOR 4 #define DM_VERSION_PATCHLEVEL 0 -#define DM_VERSION_EXTRA "-ioctl (2005-10-04)" +#define DM_VERSION_EXTRA "-ioctl (2005-01-12)" /* Status bits */ #define DM_READONLY_FLAG (1 << 0) /* In/Out */ @@ -301,13 +301,8 @@ typedef char ioctl_struct[308]; #define DM_BUFFER_FULL_FLAG (1 << 8) /* Out */ /* - * Set this to improve performance when you aren't going to use open_count. + * Set this to improve performance when you aren't going to use open_count */ #define DM_SKIP_BDGET_FLAG (1 << 9) /* In */ -/* - * Set this to avoid attempting to freeze any filesystem when suspending. - */ -#define DM_SKIP_LOCKFS_FLAG (1 << 10) /* In */ - #endif /* _LINUX_DM_IOCTL_H */ diff --git a/trunk/include/linux/elevator.h b/trunk/include/linux/elevator.h index fb80fa44c4dd..a74c27e460ba 100644 --- a/trunk/include/linux/elevator.h +++ b/trunk/include/linux/elevator.h @@ -130,7 +130,6 @@ extern int elv_try_last_merge(request_queue_t *, struct bio *); #define ELEVATOR_INSERT_FRONT 1 #define ELEVATOR_INSERT_BACK 2 #define ELEVATOR_INSERT_SORT 3 -#define ELEVATOR_INSERT_REQUEUE 4 /* * return values from elevator_may_queue_fn diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 2c9c48d65630..ed9a41a71e8b 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -760,7 +760,7 @@ extern struct file_lock *posix_test_lock(struct file *, struct file_lock *); extern int posix_lock_file(struct file *, struct file_lock *); extern int posix_lock_file_wait(struct file *, struct file_lock *); extern void posix_block_lock(struct file_lock *, struct file_lock *); -extern int posix_unblock_lock(struct file *, struct file_lock *); +extern void posix_unblock_lock(struct file *, struct file_lock *); extern int posix_locks_deadlock(struct file_lock *, struct file_lock *); extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); extern int __break_lease(struct inode *inode, unsigned int flags); @@ -1050,7 +1050,6 @@ struct inode_operations { ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); int (*removexattr) (struct dentry *, const char *); - void (*truncate_range)(struct inode *, loff_t, loff_t); }; struct seq_file; diff --git a/trunk/include/linux/fuse.h b/trunk/include/linux/fuse.h index 528959c52f1b..b76b558b03d4 100644 --- a/trunk/include/linux/fuse.h +++ b/trunk/include/linux/fuse.h @@ -14,7 +14,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 5 +#define FUSE_KERNEL_MINOR_VERSION 3 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -53,9 +53,6 @@ struct fuse_kstatfs { __u64 ffree; __u32 bsize; __u32 namelen; - __u32 frsize; - __u32 padding; - __u32 spare[6]; }; #define FATTR_MODE (1 << 0) @@ -108,8 +105,12 @@ enum fuse_opcode { FUSE_CREATE = 35 }; -/* The read buffer is required to be at least 8k, but may be much larger */ -#define FUSE_MIN_READ_BUFFER 8192 +/* Conservative buffer size for the client */ +#define FUSE_MAX_IN 8192 + +#define FUSE_NAME_MAX 1024 +#define FUSE_SYMLINK_MAX 4096 +#define FUSE_XATTR_SIZE_MAX 4096 struct fuse_entry_out { __u64 nodeid; /* Inode ID */ @@ -212,8 +213,6 @@ struct fuse_write_out { __u32 padding; }; -#define FUSE_COMPAT_STATFS_SIZE 48 - struct fuse_statfs_out { struct fuse_kstatfs st; }; @@ -244,16 +243,9 @@ struct fuse_access_in { __u32 padding; }; -struct fuse_init_in { - __u32 major; - __u32 minor; -}; - -struct fuse_init_out { +struct fuse_init_in_out { __u32 major; __u32 minor; - __u32 unused[3]; - __u32 max_write; }; struct fuse_in_header { diff --git a/trunk/include/linux/hugetlb.h b/trunk/include/linux/hugetlb.h index 68d82ad6b17c..1056717ee501 100644 --- a/trunk/include/linux/hugetlb.h +++ b/trunk/include/linux/hugetlb.h @@ -22,7 +22,7 @@ int hugetlb_report_meminfo(char *); int hugetlb_report_node_meminfo(int, char *); int is_hugepage_mem_enough(size_t); unsigned long hugetlb_total_pages(void); -struct page *alloc_huge_page(struct vm_area_struct *, unsigned long); +struct page *alloc_huge_page(void); void free_huge_page(struct page *); int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access); @@ -97,7 +97,7 @@ static inline unsigned long hugetlb_total_pages(void) #define is_hugepage_only_range(mm, addr, len) 0 #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \ do { } while (0) -#define alloc_huge_page(vma, addr) ({ NULL; }) +#define alloc_huge_page() ({ NULL; }) #define free_huge_page(p) ({ (void)(p); BUG(); }) #define hugetlb_fault(mm, vma, addr, write) ({ BUG(); 0; }) diff --git a/trunk/include/linux/i2o.h b/trunk/include/linux/i2o.h index 9ba806796667..d79c8a4bc4f8 100644 --- a/trunk/include/linux/i2o.h +++ b/trunk/include/linux/i2o.h @@ -30,7 +30,6 @@ #include #include #include /* work_struct */ -#include #include #include /* Needed for MUTEX init macros */ @@ -39,1218 +38,1091 @@ #define I2O_QUEUE_EMPTY 0xffffffff /* - * Cache strategies - */ - -/* The NULL strategy leaves everything up to the controller. This tends to be a - * pessimal but functional choice. - */ -#define CACHE_NULL 0 -/* Prefetch data when reading. We continually attempt to load the next 32 sectors - * into the controller cache. - */ -#define CACHE_PREFETCH 1 -/* Prefetch data when reading. We sometimes attempt to load the next 32 sectors - * into the controller cache. When an I/O is less <= 8K we assume its probably - * not sequential and don't prefetch (default) - */ -#define CACHE_SMARTFETCH 2 -/* Data is written to the cache and then out on to the disk. The I/O must be - * physically on the medium before the write is acknowledged (default without - * NVRAM) - */ -#define CACHE_WRITETHROUGH 17 -/* Data is written to the cache and then out on to the disk. The controller - * is permitted to write back the cache any way it wants. (default if battery - * backed NVRAM is present). It can be useful to set this for swap regardless of - * battery state. - */ -#define CACHE_WRITEBACK 18 -/* Optimise for under powered controllers, especially on RAID1 and RAID0. We - * write large I/O's directly to disk bypassing the cache to avoid the extra - * memory copy hits. Small writes are writeback cached - */ -#define CACHE_SMARTBACK 19 -/* Optimise for under powered controllers, especially on RAID1 and RAID0. We - * write large I/O's directly to disk bypassing the cache to avoid the extra - * memory copy hits. Small writes are writethrough cached. Suitable for devices - * lacking battery backup + * Message structures */ -#define CACHE_SMARTTHROUGH 20 +struct i2o_message { + union { + struct { + u8 version_offset; + u8 flags; + u16 size; + u32 target_tid:12; + u32 init_tid:12; + u32 function:8; + u32 icntxt; /* initiator context */ + u32 tcntxt; /* transaction context */ + } s; + u32 head[4]; + } u; + /* List follows */ + u32 body[0]; +}; /* - * Ioctl structures + * Each I2O device entity has one of these. There is one per device. */ +struct i2o_device { + i2o_lct_entry lct_data; /* Device LCT information */ -#define BLKI2OGRSTRAT _IOR('2', 1, int) -#define BLKI2OGWSTRAT _IOR('2', 2, int) -#define BLKI2OSRSTRAT _IOW('2', 3, int) -#define BLKI2OSWSTRAT _IOW('2', 4, int) + struct i2o_controller *iop; /* Controlling IOP */ + struct list_head list; /* node in IOP devices list */ + + struct device device; + + struct semaphore lock; /* device lock */ +}; /* - * I2O Function codes + * Event structure provided to the event handling function */ +struct i2o_event { + struct work_struct work; + struct i2o_device *i2o_dev; /* I2O device pointer from which the + event reply was initiated */ + u16 size; /* Size of data in 32-bit words */ + u32 tcntxt; /* Transaction context used at + registration */ + u32 event_indicator; /* Event indicator from reply */ + u32 data[0]; /* Event data from reply */ +}; /* - * Executive Class + * I2O classes which could be handled by the OSM */ -#define I2O_CMD_ADAPTER_ASSIGN 0xB3 -#define I2O_CMD_ADAPTER_READ 0xB2 -#define I2O_CMD_ADAPTER_RELEASE 0xB5 -#define I2O_CMD_BIOS_INFO_SET 0xA5 -#define I2O_CMD_BOOT_DEVICE_SET 0xA7 -#define I2O_CMD_CONFIG_VALIDATE 0xBB -#define I2O_CMD_CONN_SETUP 0xCA -#define I2O_CMD_DDM_DESTROY 0xB1 -#define I2O_CMD_DDM_ENABLE 0xD5 -#define I2O_CMD_DDM_QUIESCE 0xC7 -#define I2O_CMD_DDM_RESET 0xD9 -#define I2O_CMD_DDM_SUSPEND 0xAF -#define I2O_CMD_DEVICE_ASSIGN 0xB7 -#define I2O_CMD_DEVICE_RELEASE 0xB9 -#define I2O_CMD_HRT_GET 0xA8 -#define I2O_CMD_ADAPTER_CLEAR 0xBE -#define I2O_CMD_ADAPTER_CONNECT 0xC9 -#define I2O_CMD_ADAPTER_RESET 0xBD -#define I2O_CMD_LCT_NOTIFY 0xA2 -#define I2O_CMD_OUTBOUND_INIT 0xA1 -#define I2O_CMD_PATH_ENABLE 0xD3 -#define I2O_CMD_PATH_QUIESCE 0xC5 -#define I2O_CMD_PATH_RESET 0xD7 -#define I2O_CMD_STATIC_MF_CREATE 0xDD -#define I2O_CMD_STATIC_MF_RELEASE 0xDF -#define I2O_CMD_STATUS_GET 0xA0 -#define I2O_CMD_SW_DOWNLOAD 0xA9 -#define I2O_CMD_SW_UPLOAD 0xAB -#define I2O_CMD_SW_REMOVE 0xAD -#define I2O_CMD_SYS_ENABLE 0xD1 -#define I2O_CMD_SYS_MODIFY 0xC1 -#define I2O_CMD_SYS_QUIESCE 0xC3 -#define I2O_CMD_SYS_TAB_SET 0xA3 +struct i2o_class_id { + u16 class_id:12; +}; /* - * Utility Class + * I2O driver structure for OSMs */ -#define I2O_CMD_UTIL_NOP 0x00 -#define I2O_CMD_UTIL_ABORT 0x01 -#define I2O_CMD_UTIL_CLAIM 0x09 -#define I2O_CMD_UTIL_RELEASE 0x0B -#define I2O_CMD_UTIL_PARAMS_GET 0x06 -#define I2O_CMD_UTIL_PARAMS_SET 0x05 -#define I2O_CMD_UTIL_EVT_REGISTER 0x13 -#define I2O_CMD_UTIL_EVT_ACK 0x14 -#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10 -#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D -#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F -#define I2O_CMD_UTIL_LOCK 0x17 -#define I2O_CMD_UTIL_LOCK_RELEASE 0x19 -#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15 +struct i2o_driver { + char *name; /* OSM name */ + int context; /* Low 8 bits of the transaction info */ + struct i2o_class_id *classes; /* I2O classes that this OSM handles */ + + /* Message reply handler */ + int (*reply) (struct i2o_controller *, u32, struct i2o_message *); + + /* Event handler */ + void (*event) (struct i2o_event *); + + struct workqueue_struct *event_queue; /* Event queue */ + + struct device_driver driver; + + /* notification of changes */ + void (*notify_controller_add) (struct i2o_controller *); + void (*notify_controller_remove) (struct i2o_controller *); + void (*notify_device_add) (struct i2o_device *); + void (*notify_device_remove) (struct i2o_device *); + + struct semaphore lock; +}; /* - * SCSI Host Bus Adapter Class + * Contains DMA mapped address information */ -#define I2O_CMD_SCSI_EXEC 0x81 -#define I2O_CMD_SCSI_ABORT 0x83 -#define I2O_CMD_SCSI_BUSRESET 0x27 +struct i2o_dma { + void *virt; + dma_addr_t phys; + size_t len; +}; /* - * Bus Adapter Class + * Contains IO mapped address information */ -#define I2O_CMD_BUS_ADAPTER_RESET 0x85 -#define I2O_CMD_BUS_RESET 0x87 -#define I2O_CMD_BUS_SCAN 0x89 -#define I2O_CMD_BUS_QUIESCE 0x8b +struct i2o_io { + void __iomem *virt; + unsigned long phys; + unsigned long len; +}; /* - * Random Block Storage Class + * Context queue entry, used for 32-bit context on 64-bit systems */ -#define I2O_CMD_BLOCK_READ 0x30 -#define I2O_CMD_BLOCK_WRITE 0x31 -#define I2O_CMD_BLOCK_CFLUSH 0x37 -#define I2O_CMD_BLOCK_MLOCK 0x49 -#define I2O_CMD_BLOCK_MUNLOCK 0x4B -#define I2O_CMD_BLOCK_MMOUNT 0x41 -#define I2O_CMD_BLOCK_MEJECT 0x43 -#define I2O_CMD_BLOCK_POWER 0x70 +struct i2o_context_list_element { + struct list_head list; + u32 context; + void *ptr; + unsigned long timestamp; +}; -#define I2O_CMD_PRIVATE 0xFF +/* + * Each I2O controller has one of these objects + */ +struct i2o_controller { + char name[16]; + int unit; + int type; -/* Command status values */ + struct pci_dev *pdev; /* PCI device */ -#define I2O_CMD_IN_PROGRESS 0x01 -#define I2O_CMD_REJECTED 0x02 -#define I2O_CMD_FAILED 0x03 -#define I2O_CMD_COMPLETED 0x04 + unsigned int promise:1; /* Promise controller */ + unsigned int adaptec:1; /* DPT / Adaptec controller */ + unsigned int raptor:1; /* split bar */ + unsigned int no_quiesce:1; /* dont quiesce before reset */ + unsigned int short_req:1; /* use small block sizes */ + unsigned int limit_sectors:1; /* limit number of sectors / request */ + unsigned int pae_support:1; /* controller has 64-bit SGL support */ -/* I2O API function return values */ + struct list_head devices; /* list of I2O devices */ + struct list_head list; /* Controller list */ -#define I2O_RTN_NO_ERROR 0 -#define I2O_RTN_NOT_INIT 1 -#define I2O_RTN_FREE_Q_EMPTY 2 -#define I2O_RTN_TCB_ERROR 3 -#define I2O_RTN_TRANSACTION_ERROR 4 -#define I2O_RTN_ADAPTER_ALREADY_INIT 5 -#define I2O_RTN_MALLOC_ERROR 6 -#define I2O_RTN_ADPTR_NOT_REGISTERED 7 -#define I2O_RTN_MSG_REPLY_TIMEOUT 8 -#define I2O_RTN_NO_STATUS 9 -#define I2O_RTN_NO_FIRM_VER 10 -#define I2O_RTN_NO_LINK_SPEED 11 + void __iomem *in_port; /* Inbout port address */ + void __iomem *out_port; /* Outbound port address */ + void __iomem *irq_status; /* Interrupt status register address */ + void __iomem *irq_mask; /* Interrupt mask register address */ -/* Reply message status defines for all messages */ + /* Dynamic LCT related data */ -#define I2O_REPLY_STATUS_SUCCESS 0x00 -#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 -#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 -#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 -#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 -#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 -#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 -#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 -#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 -#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A -#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B -#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 + struct i2o_dma status; /* IOP status block */ -/* Status codes and Error Information for Parameter functions */ + struct i2o_dma hrt; /* HW Resource Table */ + i2o_lct *lct; /* Logical Config Table */ + struct i2o_dma dlct; /* Temp LCT */ + struct semaphore lct_lock; /* Lock for LCT updates */ + struct i2o_dma status_block; /* IOP status block */ -#define I2O_PARAMS_STATUS_SUCCESS 0x00 -#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 -#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 -#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 -#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 -#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 -#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06 -#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07 -#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08 -#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09 -#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A -#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B -#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C -#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D -#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E -#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F -#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10 - -/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error - * messages: Table 3-2 Detailed Status Codes.*/ + struct i2o_io base; /* controller messaging unit */ + struct i2o_io in_queue; /* inbound message queue Host->IOP */ + struct i2o_dma out_queue; /* outbound message queue IOP->Host */ -#define I2O_DSC_SUCCESS 0x0000 -#define I2O_DSC_BAD_KEY 0x0002 -#define I2O_DSC_TCL_ERROR 0x0003 -#define I2O_DSC_REPLY_BUFFER_FULL 0x0004 -#define I2O_DSC_NO_SUCH_PAGE 0x0005 -#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006 -#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007 -#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009 -#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A -#define I2O_DSC_DEVICE_LOCKED 0x000B -#define I2O_DSC_DEVICE_RESET 0x000C -#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D -#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E -#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F -#define I2O_DSC_INVALID_OFFSET 0x0010 -#define I2O_DSC_INVALID_PARAMETER 0x0011 -#define I2O_DSC_INVALID_REQUEST 0x0012 -#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013 -#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014 -#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015 -#define I2O_DSC_MISSING_PARAMETER 0x0016 -#define I2O_DSC_TIMEOUT 0x0017 -#define I2O_DSC_UNKNOWN_ERROR 0x0018 -#define I2O_DSC_UNKNOWN_FUNCTION 0x0019 -#define I2O_DSC_UNSUPPORTED_VERSION 0x001A -#define I2O_DSC_DEVICE_BUSY 0x001B -#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C + unsigned int battery:1; /* Has a battery backup */ + unsigned int io_alloc:1; /* An I/O resource was allocated */ + unsigned int mem_alloc:1; /* A memory resource was allocated */ -/* DetailedStatusCode defines for Block Storage Operation: Table 6-7 Detailed - Status Codes.*/ + struct resource io_resource; /* I/O resource allocated to the IOP */ + struct resource mem_resource; /* Mem resource allocated to the IOP */ -#define I2O_BSA_DSC_SUCCESS 0x0000 -#define I2O_BSA_DSC_MEDIA_ERROR 0x0001 -#define I2O_BSA_DSC_ACCESS_ERROR 0x0002 -#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003 -#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004 -#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005 -#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006 -#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007 -#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008 -#define I2O_BSA_DSC_BUS_FAILURE 0x0009 -#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A -#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B -#define I2O_BSA_DSC_DEVICE_RESET 0x000C -#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D -#define I2O_BSA_DSC_TIMEOUT 0x000E + struct device device; + struct class_device *classdev; /* I2O controller class device */ + struct i2o_device *exec; /* Executive */ +#if BITS_PER_LONG == 64 + spinlock_t context_list_lock; /* lock for context_list */ + atomic_t context_list_counter; /* needed for unique contexts */ + struct list_head context_list; /* list of context id's + and pointers */ +#endif + spinlock_t lock; /* lock for controller + configuration */ -/* FailureStatusCodes, Table 3-3 Message Failure Codes */ + void *driver_data[I2O_MAX_DRIVERS]; /* storage for drivers */ +}; -#define I2O_FSC_TRANSPORT_SERVICE_SUSPENDED 0x81 -#define I2O_FSC_TRANSPORT_SERVICE_TERMINATED 0x82 -#define I2O_FSC_TRANSPORT_CONGESTION 0x83 -#define I2O_FSC_TRANSPORT_FAILURE 0x84 -#define I2O_FSC_TRANSPORT_STATE_ERROR 0x85 -#define I2O_FSC_TRANSPORT_TIME_OUT 0x86 -#define I2O_FSC_TRANSPORT_ROUTING_FAILURE 0x87 -#define I2O_FSC_TRANSPORT_INVALID_VERSION 0x88 -#define I2O_FSC_TRANSPORT_INVALID_OFFSET 0x89 -#define I2O_FSC_TRANSPORT_INVALID_MSG_FLAGS 0x8A -#define I2O_FSC_TRANSPORT_FRAME_TOO_SMALL 0x8B -#define I2O_FSC_TRANSPORT_FRAME_TOO_LARGE 0x8C -#define I2O_FSC_TRANSPORT_INVALID_TARGET_ID 0x8D -#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_ID 0x8E -#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F -#define I2O_FSC_TRANSPORT_UNKNOWN_FAILURE 0xFF +/* + * I2O System table entry + * + * The system table contains information about all the IOPs in the + * system. It is sent to all IOPs so that they can create peer2peer + * connections between them. + */ +struct i2o_sys_tbl_entry { + u16 org_id; + u16 reserved1; + u32 iop_id:12; + u32 reserved2:20; + u16 seg_num:12; + u16 i2o_version:4; + u8 iop_state; + u8 msg_type; + u16 frame_size; + u16 reserved3; + u32 last_changed; + u32 iop_capabilities; + u32 inbound_low; + u32 inbound_high; +}; -/* Device Claim Types */ -#define I2O_CLAIM_PRIMARY 0x01000000 -#define I2O_CLAIM_MANAGEMENT 0x02000000 -#define I2O_CLAIM_AUTHORIZED 0x03000000 -#define I2O_CLAIM_SECONDARY 0x04000000 +struct i2o_sys_tbl { + u8 num_entries; + u8 version; + u16 reserved1; + u32 change_ind; + u32 reserved2; + u32 reserved3; + struct i2o_sys_tbl_entry iops[0]; +}; -/* Message header defines for VersionOffset */ -#define I2OVER15 0x0001 -#define I2OVER20 0x0002 +extern struct list_head i2o_controllers; -/* Default is 1.5 */ -#define I2OVERSION I2OVER15 +/* Message functions */ +static inline u32 i2o_msg_get(struct i2o_controller *, + struct i2o_message __iomem **); +extern u32 i2o_msg_get_wait(struct i2o_controller *, + struct i2o_message __iomem **, int); +static inline void i2o_msg_post(struct i2o_controller *, u32); +static inline int i2o_msg_post_wait(struct i2o_controller *, u32, + unsigned long); +extern int i2o_msg_post_wait_mem(struct i2o_controller *, u32, unsigned long, + struct i2o_dma *); +extern void i2o_msg_nop(struct i2o_controller *, u32); +static inline void i2o_flush_reply(struct i2o_controller *, u32); -#define SGL_OFFSET_0 I2OVERSION -#define SGL_OFFSET_4 (0x0040 | I2OVERSION) -#define SGL_OFFSET_5 (0x0050 | I2OVERSION) -#define SGL_OFFSET_6 (0x0060 | I2OVERSION) -#define SGL_OFFSET_7 (0x0070 | I2OVERSION) -#define SGL_OFFSET_8 (0x0080 | I2OVERSION) -#define SGL_OFFSET_9 (0x0090 | I2OVERSION) -#define SGL_OFFSET_10 (0x00A0 | I2OVERSION) -#define SGL_OFFSET_11 (0x00B0 | I2OVERSION) -#define SGL_OFFSET_12 (0x00C0 | I2OVERSION) -#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION) +/* IOP functions */ +extern int i2o_status_get(struct i2o_controller *); -/* Transaction Reply Lists (TRL) Control Word structure */ -#define TRL_SINGLE_FIXED_LENGTH 0x00 -#define TRL_SINGLE_VARIABLE_LENGTH 0x40 -#define TRL_MULTIPLE_FIXED_LENGTH 0x80 +extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int, + u32); +extern struct i2o_device *i2o_iop_find_device(struct i2o_controller *, u16); +extern struct i2o_controller *i2o_find_iop(int); - /* msg header defines for MsgFlags */ -#define MSG_STATIC 0x0100 -#define MSG_64BIT_CNTXT 0x0200 -#define MSG_MULTI_TRANS 0x1000 -#define MSG_FAIL 0x2000 -#define MSG_FINAL 0x4000 -#define MSG_REPLY 0x8000 +/* Functions needed for handling 64-bit pointers in 32-bit context */ +#if BITS_PER_LONG == 64 +extern u32 i2o_cntxt_list_add(struct i2o_controller *, void *); +extern void *i2o_cntxt_list_get(struct i2o_controller *, u32); +extern u32 i2o_cntxt_list_remove(struct i2o_controller *, void *); +extern u32 i2o_cntxt_list_get_ptr(struct i2o_controller *, void *); - /* minimum size msg */ -#define THREE_WORD_MSG_SIZE 0x00030000 -#define FOUR_WORD_MSG_SIZE 0x00040000 -#define FIVE_WORD_MSG_SIZE 0x00050000 -#define SIX_WORD_MSG_SIZE 0x00060000 -#define SEVEN_WORD_MSG_SIZE 0x00070000 -#define EIGHT_WORD_MSG_SIZE 0x00080000 -#define NINE_WORD_MSG_SIZE 0x00090000 -#define TEN_WORD_MSG_SIZE 0x000A0000 -#define ELEVEN_WORD_MSG_SIZE 0x000B0000 -#define I2O_MESSAGE_SIZE(x) ((x)<<16) +static inline u32 i2o_ptr_low(void *ptr) +{ + return (u32) (u64) ptr; +}; -/* special TID assignments */ -#define ADAPTER_TID 0 -#define HOST_TID 1 +static inline u32 i2o_ptr_high(void *ptr) +{ + return (u32) ((u64) ptr >> 32); +}; -/* outbound queue defines */ -#define I2O_MAX_OUTBOUND_MSG_FRAMES 128 -#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ +static inline u32 i2o_dma_low(dma_addr_t dma_addr) +{ + return (u32) (u64) dma_addr; +}; -/* inbound queue definitions */ -#define I2O_MSG_INPOOL_MIN 32 -#define I2O_INBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ +static inline u32 i2o_dma_high(dma_addr_t dma_addr) +{ + return (u32) ((u64) dma_addr >> 32); +}; +#else +static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; -#define I2O_POST_WAIT_OK 0 -#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT +static inline void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) +{ + return (void *)context; +}; -#define I2O_CONTEXT_LIST_MIN_LENGTH 15 -#define I2O_CONTEXT_LIST_USED 0x01 -#define I2O_CONTEXT_LIST_DELETED 0x02 +static inline u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; -/* timeouts */ -#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE 15 -#define I2O_TIMEOUT_MESSAGE_GET 5 -#define I2O_TIMEOUT_RESET 30 -#define I2O_TIMEOUT_STATUS_GET 5 -#define I2O_TIMEOUT_LCT_GET 360 -#define I2O_TIMEOUT_SCSI_SCB_ABORT 240 +static inline u32 i2o_cntxt_list_get_ptr(struct i2o_controller *c, void *ptr) +{ + return (u32) ptr; +}; -/* retries */ -#define I2O_HRT_GET_TRIES 3 -#define I2O_LCT_GET_TRIES 3 +static inline u32 i2o_ptr_low(void *ptr) +{ + return (u32) ptr; +}; -/* defines for max_sectors and max_phys_segments */ -#define I2O_MAX_SECTORS 1024 -#define I2O_MAX_SECTORS_LIMITED 128 -#define I2O_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS +static inline u32 i2o_ptr_high(void *ptr) +{ + return 0; +}; -/* - * Message structures - */ -struct i2o_message { - union { - struct { - u8 version_offset; - u8 flags; - u16 size; - u32 target_tid:12; - u32 init_tid:12; - u32 function:8; - u32 icntxt; /* initiator context */ - u32 tcntxt; /* transaction context */ - } s; - u32 head[4]; - } u; - /* List follows */ - u32 body[0]; +static inline u32 i2o_dma_low(dma_addr_t dma_addr) +{ + return (u32) dma_addr; }; -/* MFA and I2O message used by mempool */ -struct i2o_msg_mfa { - u32 mfa; /* MFA returned by the controller */ - struct i2o_message msg; /* I2O message */ +static inline u32 i2o_dma_high(dma_addr_t dma_addr) +{ + return 0; }; +#endif -/* - * Each I2O device entity has one of these. There is one per device. +/** + * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL + * @c: I2O controller for which the calculation should be done + * @body_size: maximum body size used for message in 32-bit words. + * + * Return the maximum number of SG elements in a SG list. */ -struct i2o_device { - i2o_lct_entry lct_data; /* Device LCT information */ +static inline u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size) +{ + i2o_status_block *sb = c->status_block.virt; + u16 sg_count = + (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) - + body_size; - struct i2o_controller *iop; /* Controlling IOP */ - struct list_head list; /* node in IOP devices list */ + if (c->pae_support) { + /* + * for 64-bit a SG attribute element must be added and each + * SG element needs 12 bytes instead of 8. + */ + sg_count -= 2; + sg_count /= 3; + } else + sg_count /= 2; - struct device device; + if (c->short_req && (sg_count > 8)) + sg_count = 8; - struct semaphore lock; /* device lock */ + return sg_count; }; -/* - * Event structure provided to the event handling function +/** + * i2o_dma_map_single - Map pointer to controller and fill in I2O message. + * @c: I2O controller + * @ptr: pointer to the data which should be mapped + * @size: size of data in bytes + * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE + * @sg_ptr: pointer to the SG list inside the I2O message + * + * This function does all necessary DMA handling and also writes the I2O + * SGL elements into the I2O message. For details on DMA handling see also + * dma_map_single(). The pointer sg_ptr will only be set to the end of the + * SG list if the allocation was successful. + * + * Returns DMA address which must be checked for failures using + * dma_mapping_error(). */ -struct i2o_event { - struct work_struct work; - struct i2o_device *i2o_dev; /* I2O device pointer from which the - event reply was initiated */ - u16 size; /* Size of data in 32-bit words */ - u32 tcntxt; /* Transaction context used at - registration */ - u32 event_indicator; /* Event indicator from reply */ - u32 data[0]; /* Event data from reply */ -}; +static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, + size_t size, + enum dma_data_direction direction, + u32 __iomem ** sg_ptr) +{ + u32 sg_flags; + u32 __iomem *mptr = *sg_ptr; + dma_addr_t dma_addr; -/* - * I2O classes which could be handled by the OSM - */ -struct i2o_class_id { - u16 class_id:12; -}; + switch (direction) { + case DMA_TO_DEVICE: + sg_flags = 0xd4000000; + break; + case DMA_FROM_DEVICE: + sg_flags = 0xd0000000; + break; + default: + return 0; + } -/* - * I2O driver structure for OSMs - */ -struct i2o_driver { - char *name; /* OSM name */ - int context; /* Low 8 bits of the transaction info */ - struct i2o_class_id *classes; /* I2O classes that this OSM handles */ + dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction); + if (!dma_mapping_error(dma_addr)) { +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) { + writel(0x7C020002, mptr++); + writel(PAGE_SIZE, mptr++); + } +#endif - /* Message reply handler */ - int (*reply) (struct i2o_controller *, u32, struct i2o_message *); + writel(sg_flags | size, mptr++); + writel(i2o_dma_low(dma_addr), mptr++); +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) + writel(i2o_dma_high(dma_addr), mptr++); +#endif + *sg_ptr = mptr; + } + return dma_addr; +}; - /* Event handler */ - void (*event) (struct i2o_event *); +/** + * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message. + * @c: I2O controller + * @sg: SG list to be mapped + * @sg_count: number of elements in the SG list + * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE + * @sg_ptr: pointer to the SG list inside the I2O message + * + * This function does all necessary DMA handling and also writes the I2O + * SGL elements into the I2O message. For details on DMA handling see also + * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG + * list if the allocation was successful. + * + * Returns 0 on failure or 1 on success. + */ +static inline int i2o_dma_map_sg(struct i2o_controller *c, + struct scatterlist *sg, int sg_count, + enum dma_data_direction direction, + u32 __iomem ** sg_ptr) +{ + u32 sg_flags; + u32 __iomem *mptr = *sg_ptr; - struct workqueue_struct *event_queue; /* Event queue */ + switch (direction) { + case DMA_TO_DEVICE: + sg_flags = 0x14000000; + break; + case DMA_FROM_DEVICE: + sg_flags = 0x10000000; + break; + default: + return 0; + } - struct device_driver driver; + sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction); + if (!sg_count) + return 0; - /* notification of changes */ - void (*notify_controller_add) (struct i2o_controller *); - void (*notify_controller_remove) (struct i2o_controller *); - void (*notify_device_add) (struct i2o_device *); - void (*notify_device_remove) (struct i2o_device *); +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) { + writel(0x7C020002, mptr++); + writel(PAGE_SIZE, mptr++); + } +#endif - struct semaphore lock; -}; + while (sg_count-- > 0) { + if (!sg_count) + sg_flags |= 0xC0000000; + writel(sg_flags | sg_dma_len(sg), mptr++); + writel(i2o_dma_low(sg_dma_address(sg)), mptr++); +#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 + if ((sizeof(dma_addr_t) > 4) && c->pae_support) + writel(i2o_dma_high(sg_dma_address(sg)), mptr++); +#endif + sg++; + } + *sg_ptr = mptr; -/* - * Contains DMA mapped address information - */ -struct i2o_dma { - void *virt; - dma_addr_t phys; - size_t len; + return 1; }; -/* - * Contains slab cache and mempool information +/** + * i2o_dma_alloc - Allocate DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: i2o_dma struct which should get the DMA buffer + * @len: length of the new DMA memory + * @gfp_mask: GFP mask + * + * Allocate a coherent DMA memory and write the pointers into addr. + * + * Returns 0 on success or -ENOMEM on failure. */ -struct i2o_pool { - char *name; - kmem_cache_t *slab; - mempool_t *mempool; -}; +static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, + size_t len, gfp_t gfp_mask) +{ + struct pci_dev *pdev = to_pci_dev(dev); + int dma_64 = 0; -/* - * Contains IO mapped address information - */ -struct i2o_io { - void __iomem *virt; - unsigned long phys; - unsigned long len; -}; + if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) { + dma_64 = 1; + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) + return -ENOMEM; + } -/* - * Context queue entry, used for 32-bit context on 64-bit systems - */ -struct i2o_context_list_element { - struct list_head list; - u32 context; - void *ptr; - unsigned long timestamp; -}; + addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask); -/* - * Each I2O controller has one of these objects - */ -struct i2o_controller { - char name[16]; - int unit; - int type; + if ((sizeof(dma_addr_t) > 4) && dma_64) + if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)) + printk(KERN_WARNING "i2o: unable to set 64-bit DMA"); - struct pci_dev *pdev; /* PCI device */ + if (!addr->virt) + return -ENOMEM; - unsigned int promise:1; /* Promise controller */ - unsigned int adaptec:1; /* DPT / Adaptec controller */ - unsigned int raptor:1; /* split bar */ - unsigned int no_quiesce:1; /* dont quiesce before reset */ - unsigned int short_req:1; /* use small block sizes */ - unsigned int limit_sectors:1; /* limit number of sectors / request */ - unsigned int pae_support:1; /* controller has 64-bit SGL support */ + memset(addr->virt, 0, len); + addr->len = len; - struct list_head devices; /* list of I2O devices */ - struct list_head list; /* Controller list */ - - void __iomem *in_port; /* Inbout port address */ - void __iomem *out_port; /* Outbound port address */ - void __iomem *irq_status; /* Interrupt status register address */ - void __iomem *irq_mask; /* Interrupt mask register address */ - - struct i2o_dma status; /* IOP status block */ - - struct i2o_dma hrt; /* HW Resource Table */ - i2o_lct *lct; /* Logical Config Table */ - struct i2o_dma dlct; /* Temp LCT */ - struct semaphore lct_lock; /* Lock for LCT updates */ - struct i2o_dma status_block; /* IOP status block */ - - struct i2o_io base; /* controller messaging unit */ - struct i2o_io in_queue; /* inbound message queue Host->IOP */ - struct i2o_dma out_queue; /* outbound message queue IOP->Host */ - - struct i2o_pool in_msg; /* mempool for inbound messages */ - - unsigned int battery:1; /* Has a battery backup */ - unsigned int io_alloc:1; /* An I/O resource was allocated */ - unsigned int mem_alloc:1; /* A memory resource was allocated */ - - struct resource io_resource; /* I/O resource allocated to the IOP */ - struct resource mem_resource; /* Mem resource allocated to the IOP */ - - struct device device; - struct i2o_device *exec; /* Executive */ -#if BITS_PER_LONG == 64 - spinlock_t context_list_lock; /* lock for context_list */ - atomic_t context_list_counter; /* needed for unique contexts */ - struct list_head context_list; /* list of context id's - and pointers */ -#endif - spinlock_t lock; /* lock for controller - configuration */ - - void *driver_data[I2O_MAX_DRIVERS]; /* storage for drivers */ + return 0; }; -/* - * I2O System table entry +/** + * i2o_dma_free - Free DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: i2o_dma struct which contains the DMA buffer * - * The system table contains information about all the IOPs in the - * system. It is sent to all IOPs so that they can create peer2peer - * connections between them. + * Free a coherent DMA memory and set virtual address of addr to NULL. */ -struct i2o_sys_tbl_entry { - u16 org_id; - u16 reserved1; - u32 iop_id:12; - u32 reserved2:20; - u16 seg_num:12; - u16 i2o_version:4; - u8 iop_state; - u8 msg_type; - u16 frame_size; - u16 reserved3; - u32 last_changed; - u32 iop_capabilities; - u32 inbound_low; - u32 inbound_high; -}; - -struct i2o_sys_tbl { - u8 num_entries; - u8 version; - u16 reserved1; - u32 change_ind; - u32 reserved2; - u32 reserved3; - struct i2o_sys_tbl_entry iops[0]; +static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr) +{ + if (addr->virt) { + if (addr->phys) + dma_free_coherent(dev, addr->len, addr->virt, + addr->phys); + else + kfree(addr->virt); + addr->virt = NULL; + } }; -extern struct list_head i2o_controllers; - -/* Message functions */ -static inline struct i2o_message *i2o_msg_get(struct i2o_controller *); -extern struct i2o_message *i2o_msg_get_wait(struct i2o_controller *, int); -static inline void i2o_msg_post(struct i2o_controller *, struct i2o_message *); -static inline int i2o_msg_post_wait(struct i2o_controller *, - struct i2o_message *, unsigned long); -extern int i2o_msg_post_wait_mem(struct i2o_controller *, struct i2o_message *, - unsigned long, struct i2o_dma *); -static inline void i2o_flush_reply(struct i2o_controller *, u32); +/** + * i2o_dma_realloc - Realloc DMA memory + * @dev: struct device pointer to the PCI device of the I2O controller + * @addr: pointer to a i2o_dma struct DMA buffer + * @len: new length of memory + * @gfp_mask: GFP mask + * + * If there was something allocated in the addr, free it first. If len > 0 + * than try to allocate it and write the addresses back to the addr + * structure. If len == 0 set the virtual address to NULL. + * + * Returns the 0 on success or negative error code on failure. + */ +static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, + size_t len, gfp_t gfp_mask) +{ + i2o_dma_free(dev, addr); -/* IOP functions */ -extern int i2o_status_get(struct i2o_controller *); + if (len) + return i2o_dma_alloc(dev, addr, len, gfp_mask); -extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int, - u32); -extern struct i2o_device *i2o_iop_find_device(struct i2o_controller *, u16); -extern struct i2o_controller *i2o_find_iop(int); + return 0; +}; -/* Functions needed for handling 64-bit pointers in 32-bit context */ -#if BITS_PER_LONG == 64 -extern u32 i2o_cntxt_list_add(struct i2o_controller *, void *); -extern void *i2o_cntxt_list_get(struct i2o_controller *, u32); -extern u32 i2o_cntxt_list_remove(struct i2o_controller *, void *); -extern u32 i2o_cntxt_list_get_ptr(struct i2o_controller *, void *); +/* I2O driver (OSM) functions */ +extern int i2o_driver_register(struct i2o_driver *); +extern void i2o_driver_unregister(struct i2o_driver *); -static inline u32 i2o_ptr_low(void *ptr) +/** + * i2o_driver_notify_controller_add - Send notification of added controller + * to a single I2O driver + * + * Send notification of added controller to a single registered driver. + */ +static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv, + struct i2o_controller *c) { - return (u32) (u64) ptr; + if (drv->notify_controller_add) + drv->notify_controller_add(c); }; -static inline u32 i2o_ptr_high(void *ptr) +/** + * i2o_driver_notify_controller_remove - Send notification of removed + * controller to a single I2O driver + * + * Send notification of removed controller to a single registered driver. + */ +static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv, + struct i2o_controller *c) { - return (u32) ((u64) ptr >> 32); + if (drv->notify_controller_remove) + drv->notify_controller_remove(c); }; -static inline u32 i2o_dma_low(dma_addr_t dma_addr) +/** + * i2o_driver_notify_device_add - Send notification of added device to a + * single I2O driver + * + * Send notification of added device to a single registered driver. + */ +static inline void i2o_driver_notify_device_add(struct i2o_driver *drv, + struct i2o_device *i2o_dev) { - return (u32) (u64) dma_addr; + if (drv->notify_device_add) + drv->notify_device_add(i2o_dev); }; -static inline u32 i2o_dma_high(dma_addr_t dma_addr) -{ - return (u32) ((u64) dma_addr >> 32); -}; -#else -static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr) +/** + * i2o_driver_notify_device_remove - Send notification of removed device + * to a single I2O driver + * + * Send notification of removed device to a single registered driver. + */ +static inline void i2o_driver_notify_device_remove(struct i2o_driver *drv, + struct i2o_device *i2o_dev) { - return (u32) ptr; + if (drv->notify_device_remove) + drv->notify_device_remove(i2o_dev); }; -static inline void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context) -{ - return (void *)context; -}; +extern void i2o_driver_notify_controller_add_all(struct i2o_controller *); +extern void i2o_driver_notify_controller_remove_all(struct i2o_controller *); +extern void i2o_driver_notify_device_add_all(struct i2o_device *); +extern void i2o_driver_notify_device_remove_all(struct i2o_device *); -static inline u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr) -{ - return (u32) ptr; -}; +/* I2O device functions */ +extern int i2o_device_claim(struct i2o_device *); +extern int i2o_device_claim_release(struct i2o_device *); -static inline u32 i2o_cntxt_list_get_ptr(struct i2o_controller *c, void *ptr) -{ - return (u32) ptr; -}; +/* Exec OSM functions */ +extern int i2o_exec_lct_get(struct i2o_controller *); -static inline u32 i2o_ptr_low(void *ptr) -{ - return (u32) ptr; -}; +/* device / driver / kobject conversion functions */ +#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver) +#define to_i2o_device(dev) container_of(dev, struct i2o_device, device) +#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device) +#define kobj_to_i2o_device(kobj) to_i2o_device(container_of(kobj, struct device, kobj)) -static inline u32 i2o_ptr_high(void *ptr) +/** + * i2o_msg_get - obtain an I2O message from the IOP + * @c: I2O controller + * @msg: pointer to a I2O message pointer + * + * This function tries to get a message slot. If no message slot is + * available do not wait until one is availabe (see also i2o_msg_get_wait). + * + * On a success the message is returned and the pointer to the message is + * set in msg. The returned message is the physical page frame offset + * address from the read port (see the i2o spec). If no message is + * available returns I2O_QUEUE_EMPTY and msg is leaved untouched. + */ +static inline u32 i2o_msg_get(struct i2o_controller *c, + struct i2o_message __iomem ** msg) { - return 0; + u32 m = readl(c->in_port); + + if (m != I2O_QUEUE_EMPTY) + *msg = c->in_queue.virt + m; + + return m; }; -static inline u32 i2o_dma_low(dma_addr_t dma_addr) +/** + * i2o_msg_post - Post I2O message to I2O controller + * @c: I2O controller to which the message should be send + * @m: the message identifier + * + * Post the message to the I2O controller. + */ +static inline void i2o_msg_post(struct i2o_controller *c, u32 m) { - return (u32) dma_addr; + writel(m, c->in_port); }; -static inline u32 i2o_dma_high(dma_addr_t dma_addr) +/** + * i2o_msg_post_wait - Post and wait a message and wait until return + * @c: controller + * @m: message to post + * @timeout: time in seconds to wait + * + * This API allows an OSM to post a message and then be told whether or + * not the system received a successful reply. If the message times out + * then the value '-ETIMEDOUT' is returned. + * + * Returns 0 on success or negative error code on failure. + */ +static inline int i2o_msg_post_wait(struct i2o_controller *c, u32 m, + unsigned long timeout) { - return 0; + return i2o_msg_post_wait_mem(c, m, timeout, NULL); }; -#endif /** - * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL - * @c: I2O controller for which the calculation should be done - * @body_size: maximum body size used for message in 32-bit words. + * i2o_flush_reply - Flush reply from I2O controller + * @c: I2O controller + * @m: the message identifier * - * Return the maximum number of SG elements in a SG list. + * The I2O controller must be informed that the reply message is not needed + * anymore. If you forget to flush the reply, the message frame can't be + * used by the controller anymore and is therefore lost. */ -static inline u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size) +static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) { - i2o_status_block *sb = c->status_block.virt; - u16 sg_count = - (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) - - body_size; - - if (c->pae_support) { - /* - * for 64-bit a SG attribute element must be added and each - * SG element needs 12 bytes instead of 8. - */ - sg_count -= 2; - sg_count /= 3; - } else - sg_count /= 2; - - if (c->short_req && (sg_count > 8)) - sg_count = 8; - - return sg_count; + writel(m, c->out_port); }; /** - * i2o_dma_map_single - Map pointer to controller and fill in I2O message. - * @c: I2O controller - * @ptr: pointer to the data which should be mapped - * @size: size of data in bytes - * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE - * @sg_ptr: pointer to the SG list inside the I2O message - * - * This function does all necessary DMA handling and also writes the I2O - * SGL elements into the I2O message. For details on DMA handling see also - * dma_map_single(). The pointer sg_ptr will only be set to the end of the - * SG list if the allocation was successful. + * i2o_out_to_virt - Turn an I2O message to a virtual address + * @c: controller + * @m: message engine value * - * Returns DMA address which must be checked for failures using - * dma_mapping_error(). + * Turn a receive message from an I2O controller bus address into + * a Linux virtual address. The shared page frame is a linear block + * so we simply have to shift the offset. This function does not + * work for sender side messages as they are ioremap objects + * provided by the I2O controller. */ -static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr, - size_t size, - enum dma_data_direction direction, - u32 ** sg_ptr) +static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c, + u32 m) { - u32 sg_flags; - u32 *mptr = *sg_ptr; - dma_addr_t dma_addr; - - switch (direction) { - case DMA_TO_DEVICE: - sg_flags = 0xd4000000; - break; - case DMA_FROM_DEVICE: - sg_flags = 0xd0000000; - break; - default: - return 0; - } - - dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction); - if (!dma_mapping_error(dma_addr)) { -#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 - if ((sizeof(dma_addr_t) > 4) && c->pae_support) { - *mptr++ = cpu_to_le32(0x7C020002); - *mptr++ = cpu_to_le32(PAGE_SIZE); - } -#endif + BUG_ON(m < c->out_queue.phys + || m >= c->out_queue.phys + c->out_queue.len); - *mptr++ = cpu_to_le32(sg_flags | size); - *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr)); -#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 - if ((sizeof(dma_addr_t) > 4) && c->pae_support) - *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr)); -#endif - *sg_ptr = mptr; - } - return dma_addr; + return c->out_queue.virt + (m - c->out_queue.phys); }; /** - * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message. - * @c: I2O controller - * @sg: SG list to be mapped - * @sg_count: number of elements in the SG list - * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE - * @sg_ptr: pointer to the SG list inside the I2O message - * - * This function does all necessary DMA handling and also writes the I2O - * SGL elements into the I2O message. For details on DMA handling see also - * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG - * list if the allocation was successful. + * i2o_msg_in_to_virt - Turn an I2O message to a virtual address + * @c: controller + * @m: message engine value * - * Returns 0 on failure or 1 on success. + * Turn a send message from an I2O controller bus address into + * a Linux virtual address. The shared page frame is a linear block + * so we simply have to shift the offset. This function does not + * work for receive side messages as they are kmalloc objects + * in a different pool. */ -static inline int i2o_dma_map_sg(struct i2o_controller *c, - struct scatterlist *sg, int sg_count, - enum dma_data_direction direction, - u32 ** sg_ptr) +static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct + i2o_controller *c, + u32 m) { - u32 sg_flags; - u32 *mptr = *sg_ptr; - - switch (direction) { - case DMA_TO_DEVICE: - sg_flags = 0x14000000; - break; - case DMA_FROM_DEVICE: - sg_flags = 0x10000000; - break; - default: - return 0; - } - - sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction); - if (!sg_count) - return 0; - -#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 - if ((sizeof(dma_addr_t) > 4) && c->pae_support) { - *mptr++ = cpu_to_le32(0x7C020002); - *mptr++ = cpu_to_le32(PAGE_SIZE); - } -#endif - - while (sg_count-- > 0) { - if (!sg_count) - sg_flags |= 0xC0000000; - *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg)); - *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg))); -#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 - if ((sizeof(dma_addr_t) > 4) && c->pae_support) - *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg))); -#endif - sg++; - } - *sg_ptr = mptr; - - return 1; + return c->in_queue.virt + m; }; -/** - * i2o_dma_alloc - Allocate DMA memory - * @dev: struct device pointer to the PCI device of the I2O controller - * @addr: i2o_dma struct which should get the DMA buffer - * @len: length of the new DMA memory - * @gfp_mask: GFP mask - * - * Allocate a coherent DMA memory and write the pointers into addr. - * - * Returns 0 on success or -ENOMEM on failure. +/* + * Endian handling wrapped into the macro - keeps the core code + * cleaner. */ -static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, - size_t len, gfp_t gfp_mask) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int dma_64 = 0; - - if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) { - dma_64 = 1; - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) - return -ENOMEM; - } - - addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask); - - if ((sizeof(dma_addr_t) > 4) && dma_64) - if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)) - printk(KERN_WARNING "i2o: unable to set 64-bit DMA"); - - if (!addr->virt) - return -ENOMEM; - memset(addr->virt, 0, len); - addr->len = len; +#define i2o_raw_writel(val, mem) __raw_writel(cpu_to_le32(val), mem) - return 0; -}; +extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int); +extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int, + void *, int); -/** - * i2o_dma_free - Free DMA memory - * @dev: struct device pointer to the PCI device of the I2O controller - * @addr: i2o_dma struct which contains the DMA buffer - * - * Free a coherent DMA memory and set virtual address of addr to NULL. - */ -static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr) -{ - if (addr->virt) { - if (addr->phys) - dma_free_coherent(dev, addr->len, addr->virt, - addr->phys); - else - kfree(addr->virt); - addr->virt = NULL; - } -}; +/* debugging and troubleshooting/diagnostic helpers. */ +#define osm_printk(level, format, arg...) \ + printk(level "%s: " format, OSM_NAME , ## arg) -/** - * i2o_dma_realloc - Realloc DMA memory - * @dev: struct device pointer to the PCI device of the I2O controller - * @addr: pointer to a i2o_dma struct DMA buffer - * @len: new length of memory - * @gfp_mask: GFP mask - * - * If there was something allocated in the addr, free it first. If len > 0 - * than try to allocate it and write the addresses back to the addr - * structure. If len == 0 set the virtual address to NULL. - * - * Returns the 0 on success or negative error code on failure. - */ -static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, - size_t len, gfp_t gfp_mask) -{ - i2o_dma_free(dev, addr); +#ifdef DEBUG +#define osm_debug(format, arg...) \ + osm_printk(KERN_DEBUG, format , ## arg) +#else +#define osm_debug(format, arg...) \ + do { } while (0) +#endif - if (len) - return i2o_dma_alloc(dev, addr, len, gfp_mask); +#define osm_err(format, arg...) \ + osm_printk(KERN_ERR, format , ## arg) +#define osm_info(format, arg...) \ + osm_printk(KERN_INFO, format , ## arg) +#define osm_warn(format, arg...) \ + osm_printk(KERN_WARNING, format , ## arg) - return 0; -}; +/* debugging functions */ +extern void i2o_report_status(const char *, const char *, struct i2o_message *); +extern void i2o_dump_message(struct i2o_message *); +extern void i2o_dump_hrt(struct i2o_controller *c); +extern void i2o_debug_state(struct i2o_controller *c); /* - * i2o_pool_alloc - Allocate an slab cache and mempool - * @mempool: pointer to struct i2o_pool to write data into. - * @name: name which is used to identify cache - * @size: size of each object - * @min_nr: minimum number of objects - * - * First allocates a slab cache with name and size. Then allocates a - * mempool which uses the slab cache for allocation and freeing. - * - * Returns 0 on success or negative error code on failure. + * Cache strategies */ -static inline int i2o_pool_alloc(struct i2o_pool *pool, const char *name, - size_t size, int min_nr) -{ - pool->name = kmalloc(strlen(name) + 1, GFP_KERNEL); - if (!pool->name) - goto exit; - strcpy(pool->name, name); - - pool->slab = - kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL, - NULL); - if (!pool->slab) - goto free_name; - - pool->mempool = - mempool_create(min_nr, mempool_alloc_slab, mempool_free_slab, - pool->slab); - if (!pool->mempool) - goto free_slab; - - return 0; - - free_slab: - kmem_cache_destroy(pool->slab); - free_name: - kfree(pool->name); - - exit: - return -ENOMEM; -}; - -/* - * i2o_pool_free - Free slab cache and mempool again - * @mempool: pointer to struct i2o_pool which should be freed - * - * Note that you have to return all objects to the mempool again before - * calling i2o_pool_free(). +/* The NULL strategy leaves everything up to the controller. This tends to be a + * pessimal but functional choice. */ -static inline void i2o_pool_free(struct i2o_pool *pool) -{ - mempool_destroy(pool->mempool); - kmem_cache_destroy(pool->slab); - kfree(pool->name); -}; - -/* I2O driver (OSM) functions */ -extern int i2o_driver_register(struct i2o_driver *); -extern void i2o_driver_unregister(struct i2o_driver *); +#define CACHE_NULL 0 +/* Prefetch data when reading. We continually attempt to load the next 32 sectors + * into the controller cache. + */ +#define CACHE_PREFETCH 1 +/* Prefetch data when reading. We sometimes attempt to load the next 32 sectors + * into the controller cache. When an I/O is less <= 8K we assume its probably + * not sequential and don't prefetch (default) + */ +#define CACHE_SMARTFETCH 2 +/* Data is written to the cache and then out on to the disk. The I/O must be + * physically on the medium before the write is acknowledged (default without + * NVRAM) + */ +#define CACHE_WRITETHROUGH 17 +/* Data is written to the cache and then out on to the disk. The controller + * is permitted to write back the cache any way it wants. (default if battery + * backed NVRAM is present). It can be useful to set this for swap regardless of + * battery state. + */ +#define CACHE_WRITEBACK 18 +/* Optimise for under powered controllers, especially on RAID1 and RAID0. We + * write large I/O's directly to disk bypassing the cache to avoid the extra + * memory copy hits. Small writes are writeback cached + */ +#define CACHE_SMARTBACK 19 +/* Optimise for under powered controllers, especially on RAID1 and RAID0. We + * write large I/O's directly to disk bypassing the cache to avoid the extra + * memory copy hits. Small writes are writethrough cached. Suitable for devices + * lacking battery backup + */ +#define CACHE_SMARTTHROUGH 20 -/** - * i2o_driver_notify_controller_add - Send notification of added controller - * to a single I2O driver - * - * Send notification of added controller to a single registered driver. +/* + * Ioctl structures */ -static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv, - struct i2o_controller *c) -{ - if (drv->notify_controller_add) - drv->notify_controller_add(c); -}; -/** - * i2o_driver_notify_controller_remove - Send notification of removed - * controller to a single I2O driver - * - * Send notification of removed controller to a single registered driver. +#define BLKI2OGRSTRAT _IOR('2', 1, int) +#define BLKI2OGWSTRAT _IOR('2', 2, int) +#define BLKI2OSRSTRAT _IOW('2', 3, int) +#define BLKI2OSWSTRAT _IOW('2', 4, int) + +/* + * I2O Function codes */ -static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv, - struct i2o_controller *c) -{ - if (drv->notify_controller_remove) - drv->notify_controller_remove(c); -}; -/** - * i2o_driver_notify_device_add - Send notification of added device to a - * single I2O driver - * - * Send notification of added device to a single registered driver. +/* + * Executive Class */ -static inline void i2o_driver_notify_device_add(struct i2o_driver *drv, - struct i2o_device *i2o_dev) -{ - if (drv->notify_device_add) - drv->notify_device_add(i2o_dev); -}; +#define I2O_CMD_ADAPTER_ASSIGN 0xB3 +#define I2O_CMD_ADAPTER_READ 0xB2 +#define I2O_CMD_ADAPTER_RELEASE 0xB5 +#define I2O_CMD_BIOS_INFO_SET 0xA5 +#define I2O_CMD_BOOT_DEVICE_SET 0xA7 +#define I2O_CMD_CONFIG_VALIDATE 0xBB +#define I2O_CMD_CONN_SETUP 0xCA +#define I2O_CMD_DDM_DESTROY 0xB1 +#define I2O_CMD_DDM_ENABLE 0xD5 +#define I2O_CMD_DDM_QUIESCE 0xC7 +#define I2O_CMD_DDM_RESET 0xD9 +#define I2O_CMD_DDM_SUSPEND 0xAF +#define I2O_CMD_DEVICE_ASSIGN 0xB7 +#define I2O_CMD_DEVICE_RELEASE 0xB9 +#define I2O_CMD_HRT_GET 0xA8 +#define I2O_CMD_ADAPTER_CLEAR 0xBE +#define I2O_CMD_ADAPTER_CONNECT 0xC9 +#define I2O_CMD_ADAPTER_RESET 0xBD +#define I2O_CMD_LCT_NOTIFY 0xA2 +#define I2O_CMD_OUTBOUND_INIT 0xA1 +#define I2O_CMD_PATH_ENABLE 0xD3 +#define I2O_CMD_PATH_QUIESCE 0xC5 +#define I2O_CMD_PATH_RESET 0xD7 +#define I2O_CMD_STATIC_MF_CREATE 0xDD +#define I2O_CMD_STATIC_MF_RELEASE 0xDF +#define I2O_CMD_STATUS_GET 0xA0 +#define I2O_CMD_SW_DOWNLOAD 0xA9 +#define I2O_CMD_SW_UPLOAD 0xAB +#define I2O_CMD_SW_REMOVE 0xAD +#define I2O_CMD_SYS_ENABLE 0xD1 +#define I2O_CMD_SYS_MODIFY 0xC1 +#define I2O_CMD_SYS_QUIESCE 0xC3 +#define I2O_CMD_SYS_TAB_SET 0xA3 -/** - * i2o_driver_notify_device_remove - Send notification of removed device - * to a single I2O driver - * - * Send notification of removed device to a single registered driver. +/* + * Utility Class */ -static inline void i2o_driver_notify_device_remove(struct i2o_driver *drv, - struct i2o_device *i2o_dev) -{ - if (drv->notify_device_remove) - drv->notify_device_remove(i2o_dev); -}; +#define I2O_CMD_UTIL_NOP 0x00 +#define I2O_CMD_UTIL_ABORT 0x01 +#define I2O_CMD_UTIL_CLAIM 0x09 +#define I2O_CMD_UTIL_RELEASE 0x0B +#define I2O_CMD_UTIL_PARAMS_GET 0x06 +#define I2O_CMD_UTIL_PARAMS_SET 0x05 +#define I2O_CMD_UTIL_EVT_REGISTER 0x13 +#define I2O_CMD_UTIL_EVT_ACK 0x14 +#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10 +#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D +#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F +#define I2O_CMD_UTIL_LOCK 0x17 +#define I2O_CMD_UTIL_LOCK_RELEASE 0x19 +#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15 -extern void i2o_driver_notify_controller_add_all(struct i2o_controller *); -extern void i2o_driver_notify_controller_remove_all(struct i2o_controller *); -extern void i2o_driver_notify_device_add_all(struct i2o_device *); -extern void i2o_driver_notify_device_remove_all(struct i2o_device *); +/* + * SCSI Host Bus Adapter Class + */ +#define I2O_CMD_SCSI_EXEC 0x81 +#define I2O_CMD_SCSI_ABORT 0x83 +#define I2O_CMD_SCSI_BUSRESET 0x27 -/* I2O device functions */ -extern int i2o_device_claim(struct i2o_device *); -extern int i2o_device_claim_release(struct i2o_device *); +/* + * Bus Adapter Class + */ +#define I2O_CMD_BUS_ADAPTER_RESET 0x85 +#define I2O_CMD_BUS_RESET 0x87 +#define I2O_CMD_BUS_SCAN 0x89 +#define I2O_CMD_BUS_QUIESCE 0x8b -/* Exec OSM functions */ -extern int i2o_exec_lct_get(struct i2o_controller *); +/* + * Random Block Storage Class + */ +#define I2O_CMD_BLOCK_READ 0x30 +#define I2O_CMD_BLOCK_WRITE 0x31 +#define I2O_CMD_BLOCK_CFLUSH 0x37 +#define I2O_CMD_BLOCK_MLOCK 0x49 +#define I2O_CMD_BLOCK_MUNLOCK 0x4B +#define I2O_CMD_BLOCK_MMOUNT 0x41 +#define I2O_CMD_BLOCK_MEJECT 0x43 +#define I2O_CMD_BLOCK_POWER 0x70 -/* device / driver / kobject conversion functions */ -#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver) -#define to_i2o_device(dev) container_of(dev, struct i2o_device, device) -#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device) -#define kobj_to_i2o_device(kobj) to_i2o_device(container_of(kobj, struct device, kobj)) +#define I2O_CMD_PRIVATE 0xFF -/** - * i2o_out_to_virt - Turn an I2O message to a virtual address - * @c: controller - * @m: message engine value - * - * Turn a receive message from an I2O controller bus address into - * a Linux virtual address. The shared page frame is a linear block - * so we simply have to shift the offset. This function does not - * work for sender side messages as they are ioremap objects - * provided by the I2O controller. - */ -static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c, - u32 m) -{ - BUG_ON(m < c->out_queue.phys - || m >= c->out_queue.phys + c->out_queue.len); +/* Command status values */ - return c->out_queue.virt + (m - c->out_queue.phys); -}; +#define I2O_CMD_IN_PROGRESS 0x01 +#define I2O_CMD_REJECTED 0x02 +#define I2O_CMD_FAILED 0x03 +#define I2O_CMD_COMPLETED 0x04 -/** - * i2o_msg_in_to_virt - Turn an I2O message to a virtual address - * @c: controller - * @m: message engine value - * - * Turn a send message from an I2O controller bus address into - * a Linux virtual address. The shared page frame is a linear block - * so we simply have to shift the offset. This function does not - * work for receive side messages as they are kmalloc objects - * in a different pool. - */ -static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct - i2o_controller *c, - u32 m) -{ - return c->in_queue.virt + m; -}; +/* I2O API function return values */ -/** - * i2o_msg_get - obtain an I2O message from the IOP - * @c: I2O controller - * - * This function tries to get a message frame. If no message frame is - * available do not wait until one is availabe (see also i2o_msg_get_wait). - * The returned pointer to the message frame is not in I/O memory, it is - * allocated from a mempool. But because a MFA is allocated from the - * controller too it is guaranteed that i2o_msg_post() will never fail. - * - * On a success a pointer to the message frame is returned. If the message - * queue is empty -EBUSY is returned and if no memory is available -ENOMEM - * is returned. - */ -static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c) -{ - struct i2o_msg_mfa *mmsg = mempool_alloc(c->in_msg.mempool, GFP_ATOMIC); - if (!mmsg) - return ERR_PTR(-ENOMEM); - - mmsg->mfa = readl(c->in_port); - if (mmsg->mfa == I2O_QUEUE_EMPTY) { - mempool_free(mmsg, c->in_msg.mempool); - return ERR_PTR(-EBUSY); - } +#define I2O_RTN_NO_ERROR 0 +#define I2O_RTN_NOT_INIT 1 +#define I2O_RTN_FREE_Q_EMPTY 2 +#define I2O_RTN_TCB_ERROR 3 +#define I2O_RTN_TRANSACTION_ERROR 4 +#define I2O_RTN_ADAPTER_ALREADY_INIT 5 +#define I2O_RTN_MALLOC_ERROR 6 +#define I2O_RTN_ADPTR_NOT_REGISTERED 7 +#define I2O_RTN_MSG_REPLY_TIMEOUT 8 +#define I2O_RTN_NO_STATUS 9 +#define I2O_RTN_NO_FIRM_VER 10 +#define I2O_RTN_NO_LINK_SPEED 11 - return &mmsg->msg; -}; +/* Reply message status defines for all messages */ -/** - * i2o_msg_post - Post I2O message to I2O controller - * @c: I2O controller to which the message should be send - * @msg: message returned by i2o_msg_get() - * - * Post the message to the I2O controller and return immediately. - */ -static inline void i2o_msg_post(struct i2o_controller *c, - struct i2o_message *msg) -{ - struct i2o_msg_mfa *mmsg; +#define I2O_REPLY_STATUS_SUCCESS 0x00 +#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 +#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 +#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 +#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 +#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 +#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 +#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 +#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 +#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A +#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B +#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 - mmsg = container_of(msg, struct i2o_msg_mfa, msg); - memcpy_toio(i2o_msg_in_to_virt(c, mmsg->mfa), msg, - (le32_to_cpu(msg->u.head[0]) >> 16) << 2); - writel(mmsg->mfa, c->in_port); - mempool_free(mmsg, c->in_msg.mempool); -}; +/* Status codes and Error Information for Parameter functions */ -/** - * i2o_msg_post_wait - Post and wait a message and wait until return - * @c: controller - * @m: message to post - * @timeout: time in seconds to wait - * - * This API allows an OSM to post a message and then be told whether or - * not the system received a successful reply. If the message times out - * then the value '-ETIMEDOUT' is returned. - * - * Returns 0 on success or negative error code on failure. - */ -static inline int i2o_msg_post_wait(struct i2o_controller *c, - struct i2o_message *msg, - unsigned long timeout) -{ - return i2o_msg_post_wait_mem(c, msg, timeout, NULL); -}; +#define I2O_PARAMS_STATUS_SUCCESS 0x00 +#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 +#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 +#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 +#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 +#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 +#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06 +#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07 +#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08 +#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09 +#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A +#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B +#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C +#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D +#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E +#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F +#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10 -/** - * i2o_msg_nop_mfa - Returns a fetched MFA back to the controller - * @c: I2O controller from which the MFA was fetched - * @mfa: MFA which should be returned - * - * This function must be used for preserved messages, because i2o_msg_nop() - * also returns the allocated memory back to the msg_pool mempool. - */ -static inline void i2o_msg_nop_mfa(struct i2o_controller *c, u32 mfa) -{ - struct i2o_message __iomem *msg; - u32 nop[3] = { - THREE_WORD_MSG_SIZE | SGL_OFFSET_0, - I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID, - 0x00000000 - }; - - msg = i2o_msg_in_to_virt(c, mfa); - memcpy_toio(msg, nop, sizeof(nop)); - writel(mfa, c->in_port); -}; +/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error + * messages: Table 3-2 Detailed Status Codes.*/ -/** - * i2o_msg_nop - Returns a message which is not used - * @c: I2O controller from which the message was created - * @msg: message which should be returned - * - * If you fetch a message via i2o_msg_get, and can't use it, you must - * return the message with this function. Otherwise the MFA is lost as well - * as the allocated memory from the mempool. - */ -static inline void i2o_msg_nop(struct i2o_controller *c, - struct i2o_message *msg) -{ - struct i2o_msg_mfa *mmsg; - mmsg = container_of(msg, struct i2o_msg_mfa, msg); +#define I2O_DSC_SUCCESS 0x0000 +#define I2O_DSC_BAD_KEY 0x0002 +#define I2O_DSC_TCL_ERROR 0x0003 +#define I2O_DSC_REPLY_BUFFER_FULL 0x0004 +#define I2O_DSC_NO_SUCH_PAGE 0x0005 +#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006 +#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007 +#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009 +#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A +#define I2O_DSC_DEVICE_LOCKED 0x000B +#define I2O_DSC_DEVICE_RESET 0x000C +#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D +#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E +#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F +#define I2O_DSC_INVALID_OFFSET 0x0010 +#define I2O_DSC_INVALID_PARAMETER 0x0011 +#define I2O_DSC_INVALID_REQUEST 0x0012 +#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013 +#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014 +#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015 +#define I2O_DSC_MISSING_PARAMETER 0x0016 +#define I2O_DSC_TIMEOUT 0x0017 +#define I2O_DSC_UNKNOWN_ERROR 0x0018 +#define I2O_DSC_UNKNOWN_FUNCTION 0x0019 +#define I2O_DSC_UNSUPPORTED_VERSION 0x001A +#define I2O_DSC_DEVICE_BUSY 0x001B +#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C - i2o_msg_nop_mfa(c, mmsg->mfa); - mempool_free(mmsg, c->in_msg.mempool); -}; +/* DetailedStatusCode defines for Block Storage Operation: Table 6-7 Detailed + Status Codes.*/ -/** - * i2o_flush_reply - Flush reply from I2O controller - * @c: I2O controller - * @m: the message identifier - * - * The I2O controller must be informed that the reply message is not needed - * anymore. If you forget to flush the reply, the message frame can't be - * used by the controller anymore and is therefore lost. - */ -static inline void i2o_flush_reply(struct i2o_controller *c, u32 m) -{ - writel(m, c->out_port); -}; +#define I2O_BSA_DSC_SUCCESS 0x0000 +#define I2O_BSA_DSC_MEDIA_ERROR 0x0001 +#define I2O_BSA_DSC_ACCESS_ERROR 0x0002 +#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003 +#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004 +#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005 +#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006 +#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007 +#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008 +#define I2O_BSA_DSC_BUS_FAILURE 0x0009 +#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A +#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B +#define I2O_BSA_DSC_DEVICE_RESET 0x000C +#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D +#define I2O_BSA_DSC_TIMEOUT 0x000E -/* - * Endian handling wrapped into the macro - keeps the core code - * cleaner. - */ +/* FailureStatusCodes, Table 3-3 Message Failure Codes */ -#define i2o_raw_writel(val, mem) __raw_writel(cpu_to_le32(val), mem) +#define I2O_FSC_TRANSPORT_SERVICE_SUSPENDED 0x81 +#define I2O_FSC_TRANSPORT_SERVICE_TERMINATED 0x82 +#define I2O_FSC_TRANSPORT_CONGESTION 0x83 +#define I2O_FSC_TRANSPORT_FAILURE 0x84 +#define I2O_FSC_TRANSPORT_STATE_ERROR 0x85 +#define I2O_FSC_TRANSPORT_TIME_OUT 0x86 +#define I2O_FSC_TRANSPORT_ROUTING_FAILURE 0x87 +#define I2O_FSC_TRANSPORT_INVALID_VERSION 0x88 +#define I2O_FSC_TRANSPORT_INVALID_OFFSET 0x89 +#define I2O_FSC_TRANSPORT_INVALID_MSG_FLAGS 0x8A +#define I2O_FSC_TRANSPORT_FRAME_TOO_SMALL 0x8B +#define I2O_FSC_TRANSPORT_FRAME_TOO_LARGE 0x8C +#define I2O_FSC_TRANSPORT_INVALID_TARGET_ID 0x8D +#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_ID 0x8E +#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F +#define I2O_FSC_TRANSPORT_UNKNOWN_FAILURE 0xFF -extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int); -extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int, - void *, int); +/* Device Claim Types */ +#define I2O_CLAIM_PRIMARY 0x01000000 +#define I2O_CLAIM_MANAGEMENT 0x02000000 +#define I2O_CLAIM_AUTHORIZED 0x03000000 +#define I2O_CLAIM_SECONDARY 0x04000000 -/* debugging and troubleshooting/diagnostic helpers. */ -#define osm_printk(level, format, arg...) \ - printk(level "%s: " format, OSM_NAME , ## arg) +/* Message header defines for VersionOffset */ +#define I2OVER15 0x0001 +#define I2OVER20 0x0002 -#ifdef DEBUG -#define osm_debug(format, arg...) \ - osm_printk(KERN_DEBUG, format , ## arg) -#else -#define osm_debug(format, arg...) \ - do { } while (0) -#endif +/* Default is 1.5 */ +#define I2OVERSION I2OVER15 -#define osm_err(format, arg...) \ - osm_printk(KERN_ERR, format , ## arg) -#define osm_info(format, arg...) \ - osm_printk(KERN_INFO, format , ## arg) -#define osm_warn(format, arg...) \ - osm_printk(KERN_WARNING, format , ## arg) +#define SGL_OFFSET_0 I2OVERSION +#define SGL_OFFSET_4 (0x0040 | I2OVERSION) +#define SGL_OFFSET_5 (0x0050 | I2OVERSION) +#define SGL_OFFSET_6 (0x0060 | I2OVERSION) +#define SGL_OFFSET_7 (0x0070 | I2OVERSION) +#define SGL_OFFSET_8 (0x0080 | I2OVERSION) +#define SGL_OFFSET_9 (0x0090 | I2OVERSION) +#define SGL_OFFSET_10 (0x00A0 | I2OVERSION) +#define SGL_OFFSET_11 (0x00B0 | I2OVERSION) +#define SGL_OFFSET_12 (0x00C0 | I2OVERSION) +#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION) -/* debugging functions */ -extern void i2o_report_status(const char *, const char *, struct i2o_message *); -extern void i2o_dump_message(struct i2o_message *); -extern void i2o_dump_hrt(struct i2o_controller *c); -extern void i2o_debug_state(struct i2o_controller *c); +/* Transaction Reply Lists (TRL) Control Word structure */ +#define TRL_SINGLE_FIXED_LENGTH 0x00 +#define TRL_SINGLE_VARIABLE_LENGTH 0x40 +#define TRL_MULTIPLE_FIXED_LENGTH 0x80 + + /* msg header defines for MsgFlags */ +#define MSG_STATIC 0x0100 +#define MSG_64BIT_CNTXT 0x0200 +#define MSG_MULTI_TRANS 0x1000 +#define MSG_FAIL 0x2000 +#define MSG_FINAL 0x4000 +#define MSG_REPLY 0x8000 + + /* minimum size msg */ +#define THREE_WORD_MSG_SIZE 0x00030000 +#define FOUR_WORD_MSG_SIZE 0x00040000 +#define FIVE_WORD_MSG_SIZE 0x00050000 +#define SIX_WORD_MSG_SIZE 0x00060000 +#define SEVEN_WORD_MSG_SIZE 0x00070000 +#define EIGHT_WORD_MSG_SIZE 0x00080000 +#define NINE_WORD_MSG_SIZE 0x00090000 +#define TEN_WORD_MSG_SIZE 0x000A0000 +#define ELEVEN_WORD_MSG_SIZE 0x000B0000 +#define I2O_MESSAGE_SIZE(x) ((x)<<16) + +/* special TID assignments */ +#define ADAPTER_TID 0 +#define HOST_TID 1 + +/* outbound queue defines */ +#define I2O_MAX_OUTBOUND_MSG_FRAMES 128 +#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */ + +#define I2O_POST_WAIT_OK 0 +#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT + +#define I2O_CONTEXT_LIST_MIN_LENGTH 15 +#define I2O_CONTEXT_LIST_USED 0x01 +#define I2O_CONTEXT_LIST_DELETED 0x02 + +/* timeouts */ +#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE 15 +#define I2O_TIMEOUT_MESSAGE_GET 5 +#define I2O_TIMEOUT_RESET 30 +#define I2O_TIMEOUT_STATUS_GET 5 +#define I2O_TIMEOUT_LCT_GET 360 +#define I2O_TIMEOUT_SCSI_SCB_ABORT 240 + +/* retries */ +#define I2O_HRT_GET_TRIES 3 +#define I2O_LCT_GET_TRIES 3 + +/* defines for max_sectors and max_phys_segments */ +#define I2O_MAX_SECTORS 1024 +#define I2O_MAX_SECTORS_LIMITED 256 +#define I2O_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS #endif /* __KERNEL__ */ #endif /* _I2O_H */ diff --git a/trunk/include/linux/irq.h b/trunk/include/linux/irq.h index 6c5d4c898ccb..f04ba20712a2 100644 --- a/trunk/include/linux/irq.h +++ b/trunk/include/linux/irq.h @@ -12,7 +12,7 @@ #include #include -#if !defined(CONFIG_S390) +#if !defined(CONFIG_ARCH_S390) #include #include @@ -221,17 +221,6 @@ extern void note_interrupt(unsigned int irq, irq_desc_t *desc, extern int can_request_irq(unsigned int irq, unsigned long irqflags); extern void init_irq_proc(void); - -#ifdef CONFIG_AUTO_IRQ_AFFINITY -extern int select_smp_affinity(unsigned int irq); -#else -static inline int -select_smp_affinity(unsigned int irq) -{ - return 1; -} -#endif - #endif extern hw_irq_controller no_irq_type; /* needed in every arch ? */ diff --git a/trunk/include/linux/jbd.h b/trunk/include/linux/jbd.h index 558cb4c26ec9..dcde7adfdce5 100644 --- a/trunk/include/linux/jbd.h +++ b/trunk/include/linux/jbd.h @@ -497,12 +497,6 @@ struct transaction_s */ struct journal_head *t_checkpoint_list; - /* - * Doubly-linked circular list of all buffers submitted for IO while - * checkpointing. [j_list_lock] - */ - struct journal_head *t_checkpoint_io_list; - /* * Doubly-linked circular list of temporary buffers currently undergoing * IO in the log [j_list_lock] @@ -849,7 +843,7 @@ extern void journal_commit_transaction(journal_t *); /* Checkpoint list management */ int __journal_clean_checkpoint_list(journal_t *journal); -int __journal_remove_checkpoint(struct journal_head *); +void __journal_remove_checkpoint(struct journal_head *); void __journal_insert_checkpoint(struct journal_head *, transaction_t *); /* Buffer IO */ diff --git a/trunk/include/linux/key.h b/trunk/include/linux/key.h index 4d189e51bc6c..53513a3be53b 100644 --- a/trunk/include/linux/key.h +++ b/trunk/include/linux/key.h @@ -193,6 +193,14 @@ struct key_type { */ int (*instantiate)(struct key *key, const void *data, size_t datalen); + /* duplicate a key of this type (optional) + * - the source key will be locked against change + * - the new description will be attached + * - the quota will have been adjusted automatically from + * source->quotalen + */ + int (*duplicate)(struct key *key, const struct key *source); + /* update a key of this type (optional) * - this method should call key_payload_reserve() to recalculate the * quota consumption diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index a43c95f8f968..e828e172ccbf 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -124,8 +124,6 @@ enum { ATA_FLAG_DEBUGMSG = (1 << 10), ATA_FLAG_NO_ATAPI = (1 << 11), /* No ATAPI support */ - ATA_FLAG_SUSPENDED = (1 << 12), /* port is suspended */ - ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ ATA_QCFLAG_SINGLE = (1 << 4), /* no s/g, just a single buffer */ @@ -438,8 +436,6 @@ extern void ata_std_ports(struct ata_ioports *ioaddr); extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, unsigned int n_ports); extern void ata_pci_remove_one (struct pci_dev *pdev); -extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state); -extern int ata_pci_device_resume(struct pci_dev *pdev); #endif /* CONFIG_PCI */ extern int ata_device_add(const struct ata_probe_ent *ent); extern void ata_host_set_remove(struct ata_host_set *host_set); @@ -449,10 +445,6 @@ extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmn extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_release(struct Scsi_Host *host); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); -extern int ata_scsi_device_resume(struct scsi_device *); -extern int ata_scsi_device_suspend(struct scsi_device *); -extern int ata_device_resume(struct ata_port *, struct ata_device *); -extern int ata_device_suspend(struct ata_port *, struct ata_device *); extern int ata_ratelimit(void); /* @@ -488,8 +480,7 @@ extern u8 ata_bmdma_status(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void ata_qc_complete(struct ata_queued_cmd *qc); extern void ata_eng_timeout(struct ata_port *ap); -extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, - struct scsi_cmnd *cmd, +extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, diff --git a/trunk/include/linux/lockd/lockd.h b/trunk/include/linux/lockd/lockd.h index 95c8fea293ba..16d4e5a08e1d 100644 --- a/trunk/include/linux/lockd/lockd.h +++ b/trunk/include/linux/lockd/lockd.h @@ -172,7 +172,7 @@ extern struct nlm_host *nlm_find_client(void); /* * Server-side lock handling */ -int nlmsvc_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *); +int nlmsvc_async_call(struct nlm_rqst *, u32, rpc_action); u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, struct nlm_lock *, int, struct nlm_cookie *); u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); diff --git a/trunk/include/linux/mempolicy.h b/trunk/include/linux/mempolicy.h index ed00b278cb93..8b67cf837ca9 100644 --- a/trunk/include/linux/mempolicy.h +++ b/trunk/include/linux/mempolicy.h @@ -109,6 +109,14 @@ static inline int mpol_equal(struct mempolicy *a, struct mempolicy *b) #define mpol_set_vma_default(vma) ((vma)->vm_policy = NULL) +/* + * Hugetlb policy. i386 hugetlb so far works with node numbers + * instead of zone lists, so give it special interfaces for now. + */ +extern int mpol_first_node(struct vm_area_struct *vma, unsigned long addr); +extern int mpol_node_valid(int nid, struct vm_area_struct *vma, + unsigned long addr); + /* * Tree of shared policies for a shared memory region. * Maintain the policies in a pseudo mm that contains vmas. The vmas @@ -148,16 +156,6 @@ extern void numa_default_policy(void); extern void numa_policy_init(void); extern void numa_policy_rebind(const nodemask_t *old, const nodemask_t *new); extern struct mempolicy default_policy; -extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, - unsigned long addr); - -extern int policy_zone; - -static inline void check_highest_zone(int k) -{ - if (k > policy_zone) - policy_zone = k; -} #else @@ -184,6 +182,17 @@ static inline struct mempolicy *mpol_copy(struct mempolicy *old) return NULL; } +static inline int mpol_first_node(struct vm_area_struct *vma, unsigned long a) +{ + return numa_node_id(); +} + +static inline int +mpol_node_valid(int nid, struct vm_area_struct *vma, unsigned long a) +{ + return 1; +} + struct shared_policy {}; static inline int mpol_set_shared_policy(struct shared_policy *info, @@ -223,15 +232,6 @@ static inline void numa_policy_rebind(const nodemask_t *old, { } -static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma, - unsigned long addr) -{ - return NODE_DATA(0)->node_zonelists + gfp_zone(GFP_HIGHUSER); -} - -static inline void check_highest_zone(int k) -{ -} #endif /* CONFIG_NUMA */ #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/mm.h b/trunk/include/linux/mm.h index bc01fff3aa01..a06a84d347fb 100644 --- a/trunk/include/linux/mm.h +++ b/trunk/include/linux/mm.h @@ -634,38 +634,14 @@ struct mempolicy *shmem_get_policy(struct vm_area_struct *vma, int shmem_lock(struct file *file, int lock, struct user_struct *user); #else #define shmem_nopage filemap_nopage - -static inline int shmem_lock(struct file *file, int lock, - struct user_struct *user) -{ - return 0; -} - -static inline int shmem_set_policy(struct vm_area_struct *vma, - struct mempolicy *new) -{ - return 0; -} - -static inline struct mempolicy *shmem_get_policy(struct vm_area_struct *vma, - unsigned long addr) -{ - return NULL; -} +#define shmem_lock(a, b, c) ({0;}) /* always in memory, no need to lock */ +#define shmem_set_policy(a, b) (0) +#define shmem_get_policy(a, b) (NULL) #endif struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags); -extern int shmem_mmap(struct file *file, struct vm_area_struct *vma); int shmem_zero_setup(struct vm_area_struct *); -#ifndef CONFIG_MMU -extern unsigned long shmem_get_unmapped_area(struct file *file, - unsigned long addr, - unsigned long len, - unsigned long pgoff, - unsigned long flags); -#endif - static inline int can_do_mlock(void) { if (capable(CAP_IPC_LOCK)) @@ -714,31 +690,14 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, } extern int vmtruncate(struct inode * inode, loff_t offset); -extern int vmtruncate_range(struct inode * inode, loff_t offset, loff_t end); extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot); extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot); +extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access); -#ifdef CONFIG_MMU -extern int __handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, - unsigned long address, int write_access); - -static inline int handle_mm_fault(struct mm_struct *mm, - struct vm_area_struct *vma, unsigned long address, - int write_access) +static inline int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long address, int write_access) { - return __handle_mm_fault(mm, vma, address, write_access) & - (~VM_FAULT_WRITE); + return __handle_mm_fault(mm, vma, address, write_access) & (~VM_FAULT_WRITE); } -#else -static inline int handle_mm_fault(struct mm_struct *mm, - struct vm_area_struct *vma, unsigned long address, - int write_access) -{ - /* should never happen if there's no MMU */ - BUG(); - return VM_FAULT_SIGBUS; -} -#endif extern int make_pages_present(unsigned long addr, unsigned long end); extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); @@ -937,8 +896,6 @@ extern unsigned long do_brk(unsigned long, unsigned long); /* filemap.c */ extern unsigned long page_unuse(struct page *); extern void truncate_inode_pages(struct address_space *, loff_t); -extern void truncate_inode_pages_range(struct address_space *, - loff_t lstart, loff_t lend); /* generic vm_area_ops exported for stackable file systems */ extern struct page *filemap_nopage(struct vm_area_struct *, unsigned long, int *); diff --git a/trunk/include/linux/mmzone.h b/trunk/include/linux/mmzone.h index c34f4a2c62f8..9f22090df7dd 100644 --- a/trunk/include/linux/mmzone.h +++ b/trunk/include/linux/mmzone.h @@ -46,6 +46,7 @@ struct zone_padding { struct per_cpu_pages { int count; /* number of pages in the list */ + int low; /* low watermark, refill needed */ int high; /* high watermark, emptying needed */ int batch; /* chunk size for buddy add/remove */ struct list_head list; /* the list of pages */ @@ -388,11 +389,6 @@ static inline struct zone *next_zone(struct zone *zone) #define for_each_zone(zone) \ for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone)) -static inline int populated_zone(struct zone *zone) -{ - return (!!zone->present_pages); -} - static inline int is_highmem_idx(int idx) { return (idx == ZONE_HIGHMEM); @@ -402,7 +398,6 @@ static inline int is_normal_idx(int idx) { return (idx == ZONE_NORMAL); } - /** * is_highmem - helper function to quickly check if a struct zone is a * highmem zone or not. This is an attempt to keep references @@ -419,16 +414,6 @@ static inline int is_normal(struct zone *zone) return zone == zone->zone_pgdat->node_zones + ZONE_NORMAL; } -static inline int is_dma32(struct zone *zone) -{ - return zone == zone->zone_pgdat->node_zones + ZONE_DMA32; -} - -static inline int is_dma(struct zone *zone) -{ - return zone == zone->zone_pgdat->node_zones + ZONE_DMA; -} - /* These two functions are used to setup the per zone pages min values */ struct ctl_table; struct file; @@ -450,6 +435,7 @@ extern struct pglist_data contig_page_data; #define NODE_DATA(nid) (&contig_page_data) #define NODE_MEM_MAP(nid) mem_map #define MAX_NODES_SHIFT 1 +#define pfn_to_nid(pfn) (0) #else /* CONFIG_NEED_MULTIPLE_NODES */ @@ -484,10 +470,6 @@ extern struct pglist_data contig_page_data; #define early_pfn_to_nid(nid) (0UL) #endif -#ifdef CONFIG_FLATMEM -#define pfn_to_nid(pfn) (0) -#endif - #define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT) #define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT) @@ -582,6 +564,11 @@ static inline int valid_section_nr(unsigned long nr) return valid_section(__nr_to_section(nr)); } +/* + * Given a kernel address, find the home node of the underlying memory. + */ +#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT) + static inline struct mem_section *__pfn_to_section(unsigned long pfn) { return __nr_to_section(pfn_to_section_nr(pfn)); @@ -611,14 +598,13 @@ static inline int pfn_valid(unsigned long pfn) * this restriction. */ #ifdef CONFIG_NUMA -#define pfn_to_nid(pfn) \ +#define pfn_to_nid early_pfn_to_nid +#endif + +#define pfn_to_pgdat(pfn) \ ({ \ - unsigned long __pfn_to_nid_pfn = (pfn); \ - page_to_nid(pfn_to_page(__pfn_to_nid_pfn)); \ + NODE_DATA(pfn_to_nid(pfn)); \ }) -#else -#define pfn_to_nid(pfn) (0) -#endif #define early_pfn_valid(pfn) pfn_valid(pfn) void sparse_init(void); @@ -627,6 +613,12 @@ void sparse_init(void); #define sparse_index_init(_sec, _nid) do {} while (0) #endif /* CONFIG_SPARSEMEM */ +#ifdef CONFIG_NODES_SPAN_OTHER_NODES +#define early_pfn_in_nid(pfn, nid) (early_pfn_to_nid(pfn) == (nid)) +#else +#define early_pfn_in_nid(pfn, nid) (1) +#endif + #ifndef early_pfn_valid #define early_pfn_valid(pfn) (1) #endif diff --git a/trunk/include/linux/nbd.h b/trunk/include/linux/nbd.h index f95d51fae733..090e210e98f0 100644 --- a/trunk/include/linux/nbd.h +++ b/trunk/include/linux/nbd.h @@ -37,26 +37,18 @@ enum { /* userspace doesn't need the nbd_device structure */ #ifdef __KERNEL__ -#include - /* values for flags field */ #define NBD_READ_ONLY 0x0001 #define NBD_WRITE_NOCHK 0x0002 -struct request; - struct nbd_device { int flags; int harderror; /* Code of hard error */ struct socket * sock; struct file * file; /* If == NULL, device is not ready, yet */ int magic; - spinlock_t queue_lock; struct list_head queue_head;/* Requests are added here... */ - struct request *active_req; - wait_queue_head_t active_wq; - struct semaphore tx_lock; struct gendisk *disk; int blksize; diff --git a/trunk/include/linux/nfs_fs.h b/trunk/include/linux/nfs_fs.h index 547d649b274e..2516adeccecf 100644 --- a/trunk/include/linux/nfs_fs.h +++ b/trunk/include/linux/nfs_fs.h @@ -38,6 +38,9 @@ # define NFS_DEBUG #endif +#define NFS_MAX_FILE_IO_BUFFER_SIZE 32768 +#define NFS_DEF_FILE_IO_BUFFER_SIZE 4096 + /* Default timeout values */ #define NFS_MAX_UDP_TIMEOUT (60*HZ) #define NFS_MAX_TCP_TIMEOUT (600*HZ) @@ -62,7 +65,6 @@ #define FLUSH_STABLE 4 /* commit to stable storage */ #define FLUSH_LOWPRI 8 /* low priority background flush */ #define FLUSH_HIGHPRI 16 /* high priority memory reclaim flush */ -#define FLUSH_NOCOMMIT 32 /* Don't send the NFSv3/v4 COMMIT */ #ifdef __KERNEL__ @@ -391,17 +393,6 @@ extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_ */ extern struct inode_operations nfs_symlink_inode_operations; -/* - * linux/fs/nfs/sysctl.c - */ -#ifdef CONFIG_SYSCTL -extern int nfs_register_sysctl(void); -extern void nfs_unregister_sysctl(void); -#else -#define nfs_register_sysctl() do { } while(0) -#define nfs_unregister_sysctl() do { } while(0) -#endif - /* * linux/fs/nfs/unlink.c */ @@ -415,12 +406,10 @@ extern int nfs_writepage(struct page *page, struct writeback_control *wbc); extern int nfs_writepages(struct address_space *, struct writeback_control *); extern int nfs_flush_incompatible(struct file *file, struct page *page); extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); -extern void nfs_writeback_done(struct rpc_task *task, void *data); -extern void nfs_writedata_release(void *data); +extern void nfs_writeback_done(struct rpc_task *task); #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) -extern void nfs_commit_done(struct rpc_task *, void *data); -extern void nfs_commit_release(void *data); +extern void nfs_commit_done(struct rpc_task *); #endif /* @@ -471,33 +460,18 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page) */ extern mempool_t *nfs_wdata_mempool; -static inline struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) +static inline struct nfs_write_data *nfs_writedata_alloc(void) { struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, SLAB_NOFS); - if (p) { memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->pages); - if (pagecount < NFS_PAGEVEC_SIZE) - p->pagevec = &p->page_array[0]; - else { - size_t size = ++pagecount * sizeof(struct page *); - p->pagevec = kmalloc(size, GFP_NOFS); - if (p->pagevec) { - memset(p->pagevec, 0, size); - } else { - mempool_free(p, nfs_wdata_mempool); - p = NULL; - } - } } return p; } static inline void nfs_writedata_free(struct nfs_write_data *p) { - if (p && (p->pagevec != &p->page_array[0])) - kfree(p->pagevec); mempool_free(p, nfs_wdata_mempool); } @@ -507,45 +481,28 @@ static inline void nfs_writedata_free(struct nfs_write_data *p) extern int nfs_readpage(struct file *, struct page *); extern int nfs_readpages(struct file *, struct address_space *, struct list_head *, unsigned); -extern void nfs_readpage_result(struct rpc_task *, void *); -extern void nfs_readdata_release(void *data); - +extern void nfs_readpage_result(struct rpc_task *); /* * Allocate and free nfs_read_data structures */ extern mempool_t *nfs_rdata_mempool; -static inline struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) +static inline struct nfs_read_data *nfs_readdata_alloc(void) { struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS); - - if (p) { + if (p) memset(p, 0, sizeof(*p)); - INIT_LIST_HEAD(&p->pages); - if (pagecount < NFS_PAGEVEC_SIZE) - p->pagevec = &p->page_array[0]; - else { - size_t size = ++pagecount * sizeof(struct page *); - p->pagevec = kmalloc(size, GFP_NOFS); - if (p->pagevec) { - memset(p->pagevec, 0, size); - } else { - mempool_free(p, nfs_rdata_mempool); - p = NULL; - } - } - } return p; } static inline void nfs_readdata_free(struct nfs_read_data *p) { - if (p && (p->pagevec != &p->page_array[0])) - kfree(p->pagevec); mempool_free(p, nfs_rdata_mempool); } +extern void nfs_readdata_release(struct rpc_task *task); + /* * linux/fs/nfs3proc.c */ diff --git a/trunk/include/linux/nfs_idmap.h b/trunk/include/linux/nfs_idmap.h index 102e56094296..a0f1f25e0ead 100644 --- a/trunk/include/linux/nfs_idmap.h +++ b/trunk/include/linux/nfs_idmap.h @@ -71,8 +71,6 @@ int nfs_map_name_to_uid(struct nfs4_client *, const char *, size_t, __u32 *); int nfs_map_group_to_gid(struct nfs4_client *, const char *, size_t, __u32 *); int nfs_map_uid_to_name(struct nfs4_client *, __u32, char *); int nfs_map_gid_to_group(struct nfs4_client *, __u32, char *); - -extern unsigned int nfs_idmap_cache_timeout; #endif /* __KERNEL__ */ #endif /* NFS_IDMAP_H */ diff --git a/trunk/include/linux/nfs_page.h b/trunk/include/linux/nfs_page.h index 66e2ed658527..da2e077b65e2 100644 --- a/trunk/include/linux/nfs_page.h +++ b/trunk/include/linux/nfs_page.h @@ -79,7 +79,9 @@ extern void nfs_clear_page_writeback(struct nfs_page *req); static inline int nfs_lock_request_dontget(struct nfs_page *req) { - return !test_and_set_bit(PG_BUSY, &req->wb_flags); + if (test_and_set_bit(PG_BUSY, &req->wb_flags)) + return 0; + return 1; } /* @@ -123,7 +125,9 @@ nfs_list_remove_request(struct nfs_page *req) static inline int nfs_defer_commit(struct nfs_page *req) { - return !test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags); + if (test_and_set_bit(PG_NEED_COMMIT, &req->wb_flags)) + return 0; + return 1; } static inline void @@ -137,7 +141,9 @@ nfs_clear_commit(struct nfs_page *req) static inline int nfs_defer_reschedule(struct nfs_page *req) { - return !test_and_set_bit(PG_NEED_RESCHED, &req->wb_flags); + if (test_and_set_bit(PG_NEED_RESCHED, &req->wb_flags)) + return 0; + return 1; } static inline void diff --git a/trunk/include/linux/nfs_xdr.h b/trunk/include/linux/nfs_xdr.h index 6d6f69ec5675..40718669b9c8 100644 --- a/trunk/include/linux/nfs_xdr.h +++ b/trunk/include/linux/nfs_xdr.h @@ -4,16 +4,6 @@ #include #include -/* - * To change the maximum rsize and wsize supported by the NFS client, adjust - * NFS_MAX_FILE_IO_SIZE. 64KB is a typical maximum, but some servers can - * support a megabyte or more. The default is left at 4096 bytes, which is - * reasonable for NFS over UDP. - */ -#define NFS_MAX_FILE_IO_SIZE (1048576U) -#define NFS_DEF_FILE_IO_SIZE (4096U) -#define NFS_MIN_FILE_IO_SIZE (1024U) - struct nfs4_fsid { __u64 major; __u64 minor; @@ -147,7 +137,7 @@ struct nfs_openres { */ struct nfs_open_confirmargs { const struct nfs_fh * fh; - nfs4_stateid * stateid; + nfs4_stateid stateid; struct nfs_seqid * seqid; }; @@ -175,62 +165,66 @@ struct nfs_closeres { * * Arguments to the lock,lockt, and locku call. * */ struct nfs_lowner { - __u64 clientid; - u32 id; + __u64 clientid; + u32 id; }; -struct nfs_lock_args { - struct nfs_fh * fh; - struct file_lock * fl; +struct nfs_lock_opargs { struct nfs_seqid * lock_seqid; nfs4_stateid * lock_stateid; struct nfs_seqid * open_seqid; nfs4_stateid * open_stateid; - struct nfs_lowner lock_owner; - unsigned char block : 1; - unsigned char reclaim : 1; - unsigned char new_lock_owner : 1; + struct nfs_lowner lock_owner; + __u32 reclaim; + __u32 new_lock_owner; }; -struct nfs_lock_res { - nfs4_stateid stateid; -}; - -struct nfs_locku_args { - struct nfs_fh * fh; - struct file_lock * fl; +struct nfs_locku_opargs { struct nfs_seqid * seqid; nfs4_stateid * stateid; }; -struct nfs_locku_res { - nfs4_stateid stateid; +struct nfs_lockargs { + struct nfs_fh * fh; + __u32 type; + __u64 offset; + __u64 length; + union { + struct nfs_lock_opargs *lock; /* LOCK */ + struct nfs_lowner *lockt; /* LOCKT */ + struct nfs_locku_opargs *locku; /* LOCKU */ + } u; }; -struct nfs_lockt_args { - struct nfs_fh * fh; - struct file_lock * fl; - struct nfs_lowner lock_owner; +struct nfs_lock_denied { + __u64 offset; + __u64 length; + __u32 type; + struct nfs_lowner owner; }; -struct nfs_lockt_res { - struct file_lock * denied; /* LOCK, LOCKT failed */ +struct nfs_lockres { + union { + nfs4_stateid stateid;/* LOCK success, LOCKU */ + struct nfs_lock_denied denied; /* LOCK failed, LOCKT success */ + } u; + const struct nfs_server * server; }; struct nfs4_delegreturnargs { const struct nfs_fh *fhandle; const nfs4_stateid *stateid; - const u32 * bitmask; -}; - -struct nfs4_delegreturnres { - struct nfs_fattr * fattr; - const struct nfs_server *server; }; /* * Arguments to the read call. */ + +#define NFS_READ_MAXIOV (9U) +#if (NFS_READ_MAXIOV > (MAX_IOVEC -2)) +#error "NFS_READ_MAXIOV is too large" +#endif + struct nfs_readargs { struct nfs_fh * fh; struct nfs_open_context *context; @@ -249,6 +243,11 @@ struct nfs_readres { /* * Arguments to the write call. */ +#define NFS_WRITE_MAXIOV (9U) +#if (NFS_WRITE_MAXIOV > (MAX_IOVEC -2)) +#error "NFS_WRITE_MAXIOV is too large" +#endif + struct nfs_writeargs { struct nfs_fh * fh; struct nfs_open_context *context; @@ -679,8 +678,6 @@ struct nfs4_server_caps_res { struct nfs_page; -#define NFS_PAGEVEC_SIZE (8U) - struct nfs_read_data { int flags; struct rpc_task task; @@ -689,14 +686,13 @@ struct nfs_read_data { struct nfs_fattr fattr; /* fattr storage */ struct list_head pages; /* Coalesced read requests */ struct nfs_page *req; /* multi ops per nfs_page */ - struct page **pagevec; + struct page *pagevec[NFS_READ_MAXIOV]; struct nfs_readargs args; struct nfs_readres res; #ifdef CONFIG_NFS_V4 unsigned long timestamp; /* For lease renewal */ #endif void (*complete) (struct nfs_read_data *, int); - struct page *page_array[NFS_PAGEVEC_SIZE + 1]; }; struct nfs_write_data { @@ -708,14 +704,13 @@ struct nfs_write_data { struct nfs_writeverf verf; struct list_head pages; /* Coalesced requests we wish to flush */ struct nfs_page *req; /* multi ops per nfs_page */ - struct page **pagevec; + struct page *pagevec[NFS_WRITE_MAXIOV]; struct nfs_writeargs args; /* argument struct */ struct nfs_writeres res; /* result struct */ #ifdef CONFIG_NFS_V4 unsigned long timestamp; /* For lease renewal */ #endif void (*complete) (struct nfs_write_data *, int); - struct page *page_array[NFS_PAGEVEC_SIZE + 1]; }; struct nfs_access_entry; diff --git a/trunk/include/linux/nfsd/xdr.h b/trunk/include/linux/nfsd/xdr.h index 3f4f7142bbe3..130d4f588a37 100644 --- a/trunk/include/linux/nfsd/xdr.h +++ b/trunk/include/linux/nfsd/xdr.h @@ -88,12 +88,10 @@ struct nfsd_readdirargs { struct nfsd_attrstat { struct svc_fh fh; - struct kstat stat; }; struct nfsd_diropres { struct svc_fh fh; - struct kstat stat; }; struct nfsd_readlinkres { @@ -103,7 +101,6 @@ struct nfsd_readlinkres { struct nfsd_readres { struct svc_fh fh; unsigned long count; - struct kstat stat; }; struct nfsd_readdirres { diff --git a/trunk/include/linux/nfsd/xdr3.h b/trunk/include/linux/nfsd/xdr3.h index a4322741f8b9..3c2a71b43bac 100644 --- a/trunk/include/linux/nfsd/xdr3.h +++ b/trunk/include/linux/nfsd/xdr3.h @@ -126,7 +126,6 @@ struct nfsd3_setaclargs { struct nfsd3_attrstat { __u32 status; struct svc_fh fh; - struct kstat stat; }; /* LOOKUP, CREATE, MKDIR, SYMLINK, MKNOD */ diff --git a/trunk/include/linux/page-flags.h b/trunk/include/linux/page-flags.h index d52999c43336..343083fec258 100644 --- a/trunk/include/linux/page-flags.h +++ b/trunk/include/linux/page-flags.h @@ -79,23 +79,13 @@ /* * Global page accounting. One instance per CPU. Only unsigned longs are * allowed. - * - * - Fields can be modified with xxx_page_state and xxx_page_state_zone at - * any time safely (which protects the instance from modification by - * interrupt. - * - The __xxx_page_state variants can be used safely when interrupts are - * disabled. - * - The __xxx_page_state variants can be used if the field is only - * modified from process context, or only modified from interrupt context. - * In this case, the field should be commented here. */ struct page_state { unsigned long nr_dirty; /* Dirty writeable pages */ unsigned long nr_writeback; /* Pages under writeback */ unsigned long nr_unstable; /* NFS unstable pages */ unsigned long nr_page_table_pages;/* Pages used for pagetables */ - unsigned long nr_mapped; /* mapped into pagetables. - * only modified from process context */ + unsigned long nr_mapped; /* mapped into pagetables */ unsigned long nr_slab; /* In slab */ #define GET_PAGE_STATE_LAST nr_slab @@ -107,40 +97,32 @@ struct page_state { unsigned long pgpgout; /* Disk writes */ unsigned long pswpin; /* swap reads */ unsigned long pswpout; /* swap writes */ - unsigned long pgalloc_high; /* page allocations */ + unsigned long pgalloc_normal; - unsigned long pgalloc_dma32; unsigned long pgalloc_dma; - unsigned long pgfree; /* page freeings */ unsigned long pgactivate; /* pages moved inactive->active */ unsigned long pgdeactivate; /* pages moved active->inactive */ unsigned long pgfault; /* faults (major+minor) */ unsigned long pgmajfault; /* faults (major only) */ - unsigned long pgrefill_high; /* inspected in refill_inactive_zone */ unsigned long pgrefill_normal; - unsigned long pgrefill_dma32; unsigned long pgrefill_dma; unsigned long pgsteal_high; /* total highmem pages reclaimed */ unsigned long pgsteal_normal; - unsigned long pgsteal_dma32; unsigned long pgsteal_dma; - unsigned long pgscan_kswapd_high;/* total highmem pages scanned */ unsigned long pgscan_kswapd_normal; - unsigned long pgscan_kswapd_dma32; - unsigned long pgscan_kswapd_dma; + unsigned long pgscan_kswapd_dma; unsigned long pgscan_direct_high;/* total highmem pages scanned */ unsigned long pgscan_direct_normal; - unsigned long pgscan_direct_dma32; unsigned long pgscan_direct_dma; - unsigned long pginodesteal; /* pages reclaimed via inode freeing */ + unsigned long slabs_scanned; /* slab objects scanned */ unsigned long kswapd_steal; /* pages reclaimed by kswapd */ unsigned long kswapd_inodesteal;/* reclaimed via kswapd inode freeing */ @@ -154,54 +136,31 @@ struct page_state { extern void get_page_state(struct page_state *ret); extern void get_page_state_node(struct page_state *ret, int node); extern void get_full_page_state(struct page_state *ret); -extern unsigned long read_page_state_offset(unsigned long offset); -extern void mod_page_state_offset(unsigned long offset, unsigned long delta); -extern void __mod_page_state_offset(unsigned long offset, unsigned long delta); +extern unsigned long __read_page_state(unsigned long offset); +extern void __mod_page_state(unsigned long offset, unsigned long delta); #define read_page_state(member) \ - read_page_state_offset(offsetof(struct page_state, member)) + __read_page_state(offsetof(struct page_state, member)) #define mod_page_state(member, delta) \ - mod_page_state_offset(offsetof(struct page_state, member), (delta)) - -#define __mod_page_state(member, delta) \ - __mod_page_state_offset(offsetof(struct page_state, member), (delta)) - -#define inc_page_state(member) mod_page_state(member, 1UL) -#define dec_page_state(member) mod_page_state(member, 0UL - 1) -#define add_page_state(member,delta) mod_page_state(member, (delta)) -#define sub_page_state(member,delta) mod_page_state(member, 0UL - (delta)) - -#define __inc_page_state(member) __mod_page_state(member, 1UL) -#define __dec_page_state(member) __mod_page_state(member, 0UL - 1) -#define __add_page_state(member,delta) __mod_page_state(member, (delta)) -#define __sub_page_state(member,delta) __mod_page_state(member, 0UL - (delta)) - -#define page_state(member) (*__page_state(offsetof(struct page_state, member))) - -#define state_zone_offset(zone, member) \ -({ \ - unsigned offset; \ - if (is_highmem(zone)) \ - offset = offsetof(struct page_state, member##_high); \ - else if (is_normal(zone)) \ - offset = offsetof(struct page_state, member##_normal); \ - else if (is_dma32(zone)) \ - offset = offsetof(struct page_state, member##_dma32); \ - else \ - offset = offsetof(struct page_state, member##_dma); \ - offset; \ -}) - -#define __mod_page_state_zone(zone, member, delta) \ - do { \ - __mod_page_state_offset(state_zone_offset(zone, member), (delta)); \ - } while (0) - -#define mod_page_state_zone(zone, member, delta) \ - do { \ - mod_page_state_offset(state_zone_offset(zone, member), (delta)); \ - } while (0) + __mod_page_state(offsetof(struct page_state, member), (delta)) + +#define inc_page_state(member) mod_page_state(member, 1UL) +#define dec_page_state(member) mod_page_state(member, 0UL - 1) +#define add_page_state(member,delta) mod_page_state(member, (delta)) +#define sub_page_state(member,delta) mod_page_state(member, 0UL - (delta)) + +#define mod_page_state_zone(zone, member, delta) \ + do { \ + unsigned offset; \ + if (is_highmem(zone)) \ + offset = offsetof(struct page_state, member##_high); \ + else if (is_normal(zone)) \ + offset = offsetof(struct page_state, member##_normal); \ + else \ + offset = offsetof(struct page_state, member##_dma); \ + __mod_page_state(offset, (delta)); \ + } while (0) /* * Manipulation of page state flags diff --git a/trunk/include/linux/parport.h b/trunk/include/linux/parport.h index f7ff0b0c4031..d2a4d9e1e6d1 100644 --- a/trunk/include/linux/parport.h +++ b/trunk/include/linux/parport.h @@ -242,6 +242,7 @@ enum ieee1284_phase { IEEE1284_PH_FWD_IDLE, IEEE1284_PH_TERMINATE, IEEE1284_PH_NEGOTIATION, + IEEE1284_PH_HBUSY_DNA, IEEE1284_PH_REV_IDLE, IEEE1284_PH_HBUSY_DAVAIL, IEEE1284_PH_REV_DATA, diff --git a/trunk/include/linux/parport_pc.h b/trunk/include/linux/parport_pc.h index 1cc0f6b1a49a..c6f762470879 100644 --- a/trunk/include/linux/parport_pc.h +++ b/trunk/include/linux/parport_pc.h @@ -79,13 +79,13 @@ static __inline__ unsigned char parport_pc_read_data(struct parport *p) } #ifdef DEBUG_PARPORT -static inline void dump_parport_state (char *str, struct parport *p) +extern __inline__ void dump_parport_state (char *str, struct parport *p) { /* here's hoping that reading these ports won't side-effect anything underneath */ unsigned char ecr = inb (ECONTROL (p)); unsigned char dcr = inb (CONTROL (p)); unsigned char dsr = inb (STATUS (p)); - static const char *const ecr_modes[] = {"SPP", "PS2", "PPFIFO", "ECP", "xXx", "yYy", "TST", "CFG"}; + static char *ecr_modes[] = {"SPP", "PS2", "PPFIFO", "ECP", "xXx", "yYy", "TST", "CFG"}; const struct parport_pc_private *priv = p->physport->private_data; int i; diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 24db7248301a..4f01710485cd 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -394,13 +394,6 @@ #define PCI_DEVICE_ID_NS_87410 0xd001 #define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d -#define PCI_DEVICE_ID_NS_CS5535_HOST_BRIDGE 0x0028 -#define PCI_DEVICE_ID_NS_CS5535_ISA_BRIDGE 0x002b -#define PCI_DEVICE_ID_NS_CS5535_IDE 0x002d -#define PCI_DEVICE_ID_NS_CS5535_AUDIO 0x002e -#define PCI_DEVICE_ID_NS_CS5535_USB 0x002f -#define PCI_DEVICE_ID_NS_CS5535_VIDEO 0x0030 - #define PCI_VENDOR_ID_TSENG 0x100c #define PCI_DEVICE_ID_TSENG_W32P_2 0x3202 #define PCI_DEVICE_ID_TSENG_W32P_b 0x3205 @@ -503,9 +496,6 @@ #define PCI_DEVICE_ID_AMD_CS5536_IDE 0x209A -#define PCI_DEVICE_ID_AMD_LX_VIDEO 0x2081 -#define PCI_DEVICE_ID_AMD_LX_AES 0x2082 - #define PCI_VENDOR_ID_TRIDENT 0x1023 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX 0x2000 #define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX 0x2001 diff --git a/trunk/include/linux/raid/md.h b/trunk/include/linux/raid/md.h index b6e0bcad84e1..13e7c4b62367 100644 --- a/trunk/include/linux/raid/md.h +++ b/trunk/include/linux/raid/md.h @@ -71,8 +71,8 @@ */ #define MD_PATCHLEVEL_VERSION 3 -extern int register_md_personality (struct mdk_personality *p); -extern int unregister_md_personality (struct mdk_personality *p); +extern int register_md_personality (int p_num, mdk_personality_t *p); +extern int unregister_md_personality (int p_num); extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev), mddev_t *mddev, const char *name); extern void md_unregister_thread (mdk_thread_t *thread); diff --git a/trunk/include/linux/raid/md_k.h b/trunk/include/linux/raid/md_k.h index 617b9506c760..46629a275ba9 100644 --- a/trunk/include/linux/raid/md_k.h +++ b/trunk/include/linux/raid/md_k.h @@ -18,19 +18,62 @@ /* and dm-bio-list.h is not under include/linux because.... ??? */ #include "../../../drivers/md/dm-bio-list.h" +#define MD_RESERVED 0UL +#define LINEAR 1UL +#define RAID0 2UL +#define RAID1 3UL +#define RAID5 4UL +#define TRANSLUCENT 5UL +#define HSM 6UL +#define MULTIPATH 7UL +#define RAID6 8UL +#define RAID10 9UL +#define FAULTY 10UL +#define MAX_PERSONALITY 11UL + #define LEVEL_MULTIPATH (-4) #define LEVEL_LINEAR (-1) #define LEVEL_FAULTY (-5) -/* we need a value for 'no level specified' and 0 - * means 'raid0', so we need something else. This is - * for internal use only - */ -#define LEVEL_NONE (-1000000) - #define MaxSector (~(sector_t)0) #define MD_THREAD_NAME_MAX 14 +static inline int pers_to_level (int pers) +{ + switch (pers) { + case FAULTY: return LEVEL_FAULTY; + case MULTIPATH: return LEVEL_MULTIPATH; + case HSM: return -3; + case TRANSLUCENT: return -2; + case LINEAR: return LEVEL_LINEAR; + case RAID0: return 0; + case RAID1: return 1; + case RAID5: return 5; + case RAID6: return 6; + case RAID10: return 10; + } + BUG(); + return MD_RESERVED; +} + +static inline int level_to_pers (int level) +{ + switch (level) { + case LEVEL_FAULTY: return FAULTY; + case LEVEL_MULTIPATH: return MULTIPATH; + case -3: return HSM; + case -2: return TRANSLUCENT; + case LEVEL_LINEAR: return LINEAR; + case 0: return RAID0; + case 1: return RAID1; + case 4: + case 5: return RAID5; + case 6: return RAID6; + case 10: return RAID10; + } + return MD_RESERVED; +} + typedef struct mddev_s mddev_t; typedef struct mdk_rdev_s mdk_rdev_t; @@ -95,16 +138,14 @@ struct mdk_rdev_s atomic_t read_errors; /* number of consecutive read errors that * we have tried to ignore. */ - atomic_t corrected_errors; /* number of corrected read errors, - * for reporting to userspace and storing - * in superblock. - */ }; +typedef struct mdk_personality_s mdk_personality_t; + struct mddev_s { void *private; - struct mdk_personality *pers; + mdk_personality_t *pers; dev_t unit; int md_minor; struct list_head disks; @@ -123,7 +164,6 @@ struct mddev_s int chunk_size; time_t ctime, utime; int level, layout; - char clevel[16]; int raid_disks; int max_disks; sector_t size; /* used size of component devices */ @@ -143,11 +183,6 @@ struct mddev_s sector_t resync_mismatches; /* count of sectors where * parity/replica mismatch found */ - /* if zero, use the system-wide default */ - int sync_speed_min; - int sync_speed_max; - - int ok_start_degraded; /* recovery/resync flags * NEEDED: we might need to start a resync/recover * RUNNING: a thread is running, or about to be started @@ -230,11 +265,9 @@ static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sect atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io); } -struct mdk_personality +struct mdk_personality_s { char *name; - int level; - struct list_head list; struct module *owner; int (*make_request)(request_queue_t *q, struct bio *bio); int (*run)(mddev_t *mddev); @@ -272,6 +305,8 @@ static inline char * mdname (mddev_t * mddev) return mddev->gendisk ? mddev->gendisk->disk_name : "mdX"; } +extern mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr); + /* * iterates through some rdev ringlist. It's safe to remove the * current 'rdev'. Dont touch 'tmp' though. @@ -331,10 +366,5 @@ do { \ __wait_event_lock_irq(wq, condition, lock, cmd); \ } while (0) -static inline void safe_put_page(struct page *p) -{ - if (p) put_page(p); -} - #endif diff --git a/trunk/include/linux/raid/raid1.h b/trunk/include/linux/raid/raid1.h index 9d5494aaac0f..292b98f2b408 100644 --- a/trunk/include/linux/raid/raid1.h +++ b/trunk/include/linux/raid/raid1.h @@ -45,8 +45,6 @@ struct r1_private_data_s { spinlock_t resync_lock; int nr_pending; - int nr_waiting; - int nr_queued; int barrier; sector_t next_resync; int fullsync; /* set to 1 if a full sync is needed, @@ -54,12 +52,11 @@ struct r1_private_data_s { * Cleared when a sync completes. */ - wait_queue_head_t wait_barrier; + wait_queue_head_t wait_idle; + wait_queue_head_t wait_resume; struct pool_info *poolinfo; - struct page *tmppage; - mempool_t *r1bio_pool; mempool_t *r1buf_pool; }; @@ -109,13 +106,6 @@ struct r1bio_s { /* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/ }; -/* when we get a read error on a read-only array, we redirect to another - * device without failing the first device, or trying to over-write to - * correct the read error. To keep track of bad blocks on a per-bio - * level, we store IO_BLOCKED in the appropriate 'bios' pointer - */ -#define IO_BLOCKED ((struct bio*)1) - /* bits for r1bio.state */ #define R1BIO_Uptodate 0 #define R1BIO_IsSync 1 diff --git a/trunk/include/linux/raid/raid10.h b/trunk/include/linux/raid/raid10.h index b1103298a8c2..60708789c8f9 100644 --- a/trunk/include/linux/raid/raid10.h +++ b/trunk/include/linux/raid/raid10.h @@ -35,26 +35,18 @@ struct r10_private_data_s { sector_t chunk_mask; struct list_head retry_list; - /* queue pending writes and submit them on unplug */ - struct bio_list pending_bio_list; - + /* for use when syncing mirrors: */ spinlock_t resync_lock; int nr_pending; - int nr_waiting; - int nr_queued; int barrier; sector_t next_resync; - int fullsync; /* set to 1 if a full sync is needed, - * (fresh device added). - * Cleared when a sync completes. - */ - wait_queue_head_t wait_barrier; + wait_queue_head_t wait_idle; + wait_queue_head_t wait_resume; mempool_t *r10bio_pool; mempool_t *r10buf_pool; - struct page *tmppage; }; typedef struct r10_private_data_s conf_t; @@ -104,16 +96,8 @@ struct r10bio_s { } devs[0]; }; -/* when we get a read error on a read-only array, we redirect to another - * device without failing the first device, or trying to over-write to - * correct the read error. To keep track of bad blocks on a per-bio - * level, we store IO_BLOCKED in the appropriate 'bios' pointer - */ -#define IO_BLOCKED ((struct bio*)1) - /* bits for r10bio.state */ #define R10BIO_Uptodate 0 #define R10BIO_IsSync 1 #define R10BIO_IsRecover 2 -#define R10BIO_Degraded 3 #endif diff --git a/trunk/include/linux/raid/raid5.h b/trunk/include/linux/raid/raid5.h index 394da8207b34..f025ba6fb14c 100644 --- a/trunk/include/linux/raid/raid5.h +++ b/trunk/include/linux/raid/raid5.h @@ -126,7 +126,7 @@ */ struct stripe_head { - struct hlist_node hash; + struct stripe_head *hash_next, **hash_pprev; /* hash pointers */ struct list_head lru; /* inactive_list or handle_list */ struct raid5_private_data *raid_conf; sector_t sector; /* sector of this row */ @@ -152,6 +152,7 @@ struct stripe_head { #define R5_Insync 3 /* rdev && rdev->in_sync at start */ #define R5_Wantread 4 /* want to schedule a read */ #define R5_Wantwrite 5 +#define R5_Syncio 6 /* this io need to be accounted as resync io */ #define R5_Overlap 7 /* There is a pending overlapping request on this block */ #define R5_ReadError 8 /* seen a read error here recently */ #define R5_ReWrite 9 /* have tried to over-write the readerror */ @@ -204,7 +205,7 @@ struct disk_info { }; struct raid5_private_data { - struct hlist_head *stripe_hashtbl; + struct stripe_head **stripe_hashtbl; mddev_t *mddev; struct disk_info *spare; int chunk_size, level, algorithm; @@ -227,8 +228,6 @@ struct raid5_private_data { * Cleared when a sync completes. */ - struct page *spare_page; /* Used when checking P/Q in raid6 */ - /* * Free stripes pool */ diff --git a/trunk/include/linux/ramfs.h b/trunk/include/linux/ramfs.h index 953b6df5d037..e0a4faa9610c 100644 --- a/trunk/include/linux/ramfs.h +++ b/trunk/include/linux/ramfs.h @@ -5,16 +5,6 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev); struct super_block *ramfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data); -#ifndef CONFIG_MMU -extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file, - unsigned long addr, - unsigned long len, - unsigned long pgoff, - unsigned long flags); - -extern int ramfs_nommu_mmap(struct file *file, struct vm_area_struct *vma); -#endif - extern struct file_operations ramfs_file_operations; extern struct vm_operations_struct generic_file_vm_ops; diff --git a/trunk/include/linux/rmap.h b/trunk/include/linux/rmap.h index 9d6fbeef2104..33261f1d2239 100644 --- a/trunk/include/linux/rmap.h +++ b/trunk/include/linux/rmap.h @@ -71,7 +71,6 @@ void __anon_vma_link(struct vm_area_struct *); * rmap interfaces called when adding or removing pte of page */ void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); -void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); void page_add_file_rmap(struct page *); void page_remove_rmap(struct page *); diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 7da33619d5d0..b0ad6f30679e 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -254,12 +254,25 @@ extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long); * The mm counters are not protected by its page_table_lock, * so must be incremented atomically. */ -#define set_mm_counter(mm, member, value) atomic_long_set(&(mm)->_##member, value) -#define get_mm_counter(mm, member) ((unsigned long)atomic_long_read(&(mm)->_##member)) -#define add_mm_counter(mm, member, value) atomic_long_add(value, &(mm)->_##member) -#define inc_mm_counter(mm, member) atomic_long_inc(&(mm)->_##member) -#define dec_mm_counter(mm, member) atomic_long_dec(&(mm)->_##member) -typedef atomic_long_t mm_counter_t; +#ifdef ATOMIC64_INIT +#define set_mm_counter(mm, member, value) atomic64_set(&(mm)->_##member, value) +#define get_mm_counter(mm, member) ((unsigned long)atomic64_read(&(mm)->_##member)) +#define add_mm_counter(mm, member, value) atomic64_add(value, &(mm)->_##member) +#define inc_mm_counter(mm, member) atomic64_inc(&(mm)->_##member) +#define dec_mm_counter(mm, member) atomic64_dec(&(mm)->_##member) +typedef atomic64_t mm_counter_t; +#else /* !ATOMIC64_INIT */ +/* + * The counters wrap back to 0 at 2^32 * PAGE_SIZE, + * that is, at 16TB if using 4kB page size. + */ +#define set_mm_counter(mm, member, value) atomic_set(&(mm)->_##member, value) +#define get_mm_counter(mm, member) ((unsigned long)atomic_read(&(mm)->_##member)) +#define add_mm_counter(mm, member, value) atomic_add(value, &(mm)->_##member) +#define inc_mm_counter(mm, member) atomic_inc(&(mm)->_##member) +#define dec_mm_counter(mm, member) atomic_dec(&(mm)->_##member) +typedef atomic_t mm_counter_t; +#endif /* !ATOMIC64_INIT */ #else /* NR_CPUS < CONFIG_SPLIT_PTLOCK_CPUS */ /* diff --git a/trunk/include/linux/sunrpc/clnt.h b/trunk/include/linux/sunrpc/clnt.h index f147e6b84332..ab151bbb66df 100644 --- a/trunk/include/linux/sunrpc/clnt.h +++ b/trunk/include/linux/sunrpc/clnt.h @@ -49,6 +49,7 @@ struct rpc_clnt { unsigned int cl_softrtry : 1,/* soft timeouts */ cl_intr : 1,/* interruptible */ + cl_chatty : 1,/* be verbose */ cl_autobind : 1,/* use getport() */ cl_oneshot : 1,/* dispose after use */ cl_dead : 1;/* abandoned */ @@ -125,8 +126,7 @@ int rpc_register(u32, u32, int, unsigned short, int *); void rpc_call_setup(struct rpc_task *, struct rpc_message *, int); int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, - int flags, const struct rpc_call_ops *tk_ops, - void *calldata); + int flags, rpc_action callback, void *clntdata); int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags); void rpc_restart_call(struct rpc_task *); @@ -134,7 +134,6 @@ void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset); void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset); void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); size_t rpc_max_payload(struct rpc_clnt *); -void rpc_force_rebind(struct rpc_clnt *); int rpc_ping(struct rpc_clnt *clnt, int flags); static __inline__ diff --git a/trunk/include/linux/sunrpc/gss_spkm3.h b/trunk/include/linux/sunrpc/gss_spkm3.h index 336e218c2782..0beb2cf00a84 100644 --- a/trunk/include/linux/sunrpc/gss_spkm3.h +++ b/trunk/include/linux/sunrpc/gss_spkm3.h @@ -48,7 +48,7 @@ u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struc #define CKSUMTYPE_RSA_MD5 0x0007 s32 make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, - int body_offset, struct xdr_netobj *cksum); + struct xdr_netobj *cksum); void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits); int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen); diff --git a/trunk/include/linux/sunrpc/sched.h b/trunk/include/linux/sunrpc/sched.h index 8b25629accd8..4d77e90d0b30 100644 --- a/trunk/include/linux/sunrpc/sched.h +++ b/trunk/include/linux/sunrpc/sched.h @@ -27,7 +27,6 @@ struct rpc_message { struct rpc_cred * rpc_cred; /* Credentials */ }; -struct rpc_call_ops; struct rpc_wait_queue; struct rpc_wait { struct list_head list; /* wait queue links */ @@ -42,7 +41,6 @@ struct rpc_task { #ifdef RPC_DEBUG unsigned long tk_magic; /* 0xf00baa */ #endif - atomic_t tk_count; /* Reference count */ struct list_head tk_task; /* global list of tasks */ struct rpc_clnt * tk_client; /* RPC client */ struct rpc_rqst * tk_rqstp; /* RPC request */ @@ -52,6 +50,8 @@ struct rpc_task { * RPC call state */ struct rpc_message tk_msg; /* RPC call info */ + __u32 * tk_buffer; /* XDR buffer */ + size_t tk_bufsize; __u8 tk_garb_retry; __u8 tk_cred_retry; @@ -61,12 +61,13 @@ struct rpc_task { * timeout_fn to be executed by timer bottom half * callback to be executed after waking up * action next procedure for async tasks - * tk_ops caller callbacks + * exit exit async task and report to caller */ void (*tk_timeout_fn)(struct rpc_task *); void (*tk_callback)(struct rpc_task *); void (*tk_action)(struct rpc_task *); - const struct rpc_call_ops *tk_ops; + void (*tk_exit)(struct rpc_task *); + void (*tk_release)(struct rpc_task *); void * tk_calldata; /* @@ -77,6 +78,7 @@ struct rpc_task { struct timer_list tk_timer; /* kernel timer */ unsigned long tk_timeout; /* timeout for rpc_sleep() */ unsigned short tk_flags; /* misc flags */ + unsigned char tk_active : 1;/* Task has been activated */ unsigned char tk_priority : 2;/* Task priority */ unsigned long tk_runstate; /* Task run status */ struct workqueue_struct *tk_workqueue; /* Normally rpciod, but could @@ -109,13 +111,6 @@ struct rpc_task { typedef void (*rpc_action)(struct rpc_task *); -struct rpc_call_ops { - void (*rpc_call_prepare)(struct rpc_task *, void *); - void (*rpc_call_done)(struct rpc_task *, void *); - void (*rpc_release)(void *); -}; - - /* * RPC task flags */ @@ -134,6 +129,7 @@ struct rpc_call_ops { #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) +#define RPC_IS_ACTIVATED(t) ((t)->tk_active) #define RPC_DO_CALLBACK(t) ((t)->tk_callback != NULL) #define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT) #define RPC_TASK_UNINTERRUPTIBLE(t) ((t)->tk_flags & RPC_TASK_NOINTR) @@ -142,7 +138,6 @@ struct rpc_call_ops { #define RPC_TASK_QUEUED 1 #define RPC_TASK_WAKEUP 2 #define RPC_TASK_HAS_TIMER 3 -#define RPC_TASK_ACTIVE 4 #define RPC_IS_RUNNING(t) (test_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)) #define rpc_set_running(t) (set_bit(RPC_TASK_RUNNING, &(t)->tk_runstate)) @@ -173,15 +168,6 @@ struct rpc_call_ops { smp_mb__after_clear_bit(); \ } while (0) -#define RPC_IS_ACTIVATED(t) (test_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)) -#define rpc_set_active(t) (set_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate)) -#define rpc_clear_active(t) \ - do { \ - smp_mb__before_clear_bit(); \ - clear_bit(RPC_TASK_ACTIVE, &(t)->tk_runstate); \ - smp_mb__after_clear_bit(); \ - } while(0) - /* * Task priorities. * Note: if you change these, you must also change @@ -242,16 +228,11 @@ struct rpc_wait_queue { /* * Function prototypes */ -struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags, - const struct rpc_call_ops *ops, void *data); -struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, - const struct rpc_call_ops *ops, void *data); +struct rpc_task *rpc_new_task(struct rpc_clnt *, rpc_action, int flags); struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent); -void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, - int flags, const struct rpc_call_ops *ops, - void *data); +void rpc_init_task(struct rpc_task *, struct rpc_clnt *, + rpc_action exitfunc, int flags); void rpc_release_task(struct rpc_task *); -void rpc_exit_task(struct rpc_task *); void rpc_killall_tasks(struct rpc_clnt *); int rpc_execute(struct rpc_task *); void rpc_run_child(struct rpc_task *parent, struct rpc_task *child, @@ -266,11 +247,9 @@ struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *); void rpc_wake_up_status(struct rpc_wait_queue *, int); void rpc_delay(struct rpc_task *, unsigned long); void * rpc_malloc(struct rpc_task *, size_t); -void rpc_free(struct rpc_task *); int rpciod_up(void); void rpciod_down(void); void rpciod_wake_up(void); -int __rpc_wait_for_completion_task(struct rpc_task *task, int (*)(void *)); #ifdef RPC_DEBUG void rpc_show_tasks(void); #endif @@ -280,12 +259,7 @@ void rpc_destroy_mempool(void); static inline void rpc_exit(struct rpc_task *task, int status) { task->tk_status = status; - task->tk_action = rpc_exit_task; -} - -static inline int rpc_wait_for_completion_task(struct rpc_task *task) -{ - return __rpc_wait_for_completion_task(task, NULL); + task->tk_action = NULL; } #ifdef RPC_DEBUG diff --git a/trunk/include/linux/sunrpc/xdr.h b/trunk/include/linux/sunrpc/xdr.h index 84c35d42d250..5da968729cf8 100644 --- a/trunk/include/linux/sunrpc/xdr.h +++ b/trunk/include/linux/sunrpc/xdr.h @@ -91,6 +91,7 @@ struct xdr_buf { u32 * xdr_encode_opaque_fixed(u32 *p, const void *ptr, unsigned int len); u32 * xdr_encode_opaque(u32 *p, const void *ptr, unsigned int len); u32 * xdr_encode_string(u32 *p, const char *s); +u32 * xdr_decode_string(u32 *p, char **sp, int *lenp, int maxlen); u32 * xdr_decode_string_inplace(u32 *p, char **sp, int *lenp, int maxlen); u32 * xdr_encode_netobj(u32 *p, const struct xdr_netobj *); u32 * xdr_decode_netobj(u32 *p, struct xdr_netobj *); @@ -133,6 +134,11 @@ xdr_adjust_iovec(struct kvec *iov, u32 *p) return iov->iov_len = ((u8 *) p - (u8 *) iov->iov_base); } +/* + * Maximum number of iov's we use. + */ +#define MAX_IOVEC (12) + /* * XDR buffer helper functions */ diff --git a/trunk/include/linux/sunrpc/xprt.h b/trunk/include/linux/sunrpc/xprt.h index 6ef99b14ff09..3b8b6e823c70 100644 --- a/trunk/include/linux/sunrpc/xprt.h +++ b/trunk/include/linux/sunrpc/xprt.h @@ -79,19 +79,21 @@ struct rpc_rqst { void (*rq_release_snd_buf)(struct rpc_rqst *); /* release rq_enc_pages */ struct list_head rq_list; - __u32 * rq_buffer; /* XDR encode buffer */ - size_t rq_bufsize; - struct xdr_buf rq_private_buf; /* The receive buffer * used in the softirq. */ unsigned long rq_majortimeo; /* major timeout alarm */ unsigned long rq_timeout; /* Current timeout value */ unsigned int rq_retries; /* # of retries */ + /* + * For authentication (e.g. auth_des) + */ + u32 rq_creddata[2]; /* * Partial send handling */ + u32 rq_bytes_sent; /* Bytes we have sent */ unsigned long rq_xtime; /* when transmitted */ @@ -104,10 +106,7 @@ struct rpc_xprt_ops { void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize); int (*reserve_xprt)(struct rpc_task *task); void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); - void (*set_port)(struct rpc_xprt *xprt, unsigned short port); void (*connect)(struct rpc_task *task); - void * (*buf_alloc)(struct rpc_task *task, size_t size); - void (*buf_free)(struct rpc_task *task); int (*send_request)(struct rpc_task *task); void (*set_retrans_timeout)(struct rpc_task *task); void (*timer)(struct rpc_task *task); @@ -254,7 +253,6 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to); #define XPRT_LOCKED (0) #define XPRT_CONNECTED (1) #define XPRT_CONNECTING (2) -#define XPRT_CLOSE_WAIT (3) static inline void xprt_set_connected(struct rpc_xprt *xprt) { diff --git a/trunk/include/linux/suspend.h b/trunk/include/linux/suspend.h index 5dc94e777fab..a61c04f804b2 100644 --- a/trunk/include/linux/suspend.h +++ b/trunk/include/linux/suspend.h @@ -14,7 +14,11 @@ typedef struct pbe { unsigned long address; /* address of the copy */ unsigned long orig_address; /* original address of page */ - struct pbe *next; + swp_entry_t swap_address; + + struct pbe *next; /* also used as scratch space at + * end of page (see link, diskpage) + */ } suspend_pagedir_t; #define for_each_pbe(pbe, pblist) \ @@ -73,6 +77,6 @@ unsigned long get_safe_page(gfp_t gfp_mask); * XXX: We try to keep some more pages free so that I/O operations succeed * without paging. Might this be more? */ -#define PAGES_FOR_IO 1024 +#define PAGES_FOR_IO 512 #endif /* _LINUX_SWSUSP_H */ diff --git a/trunk/include/linux/swap.h b/trunk/include/linux/swap.h index 556617bcf7ac..508668f840b6 100644 --- a/trunk/include/linux/swap.h +++ b/trunk/include/linux/swap.h @@ -172,6 +172,7 @@ extern void swap_setup(void); /* linux/mm/vmscan.c */ extern int try_to_free_pages(struct zone **, gfp_t); +extern int zone_reclaim(struct zone *, gfp_t, unsigned int); extern int shrink_all_memory(int); extern int vm_swappiness; @@ -209,7 +210,6 @@ extern unsigned int nr_swapfiles; extern struct swap_info_struct swap_info[]; extern void si_swapinfo(struct sysinfo *); extern swp_entry_t get_swap_page(void); -extern swp_entry_t get_swap_page_of_type(int type); extern int swap_duplicate(swp_entry_t); extern int valid_swaphandles(swp_entry_t, unsigned long *); extern void swap_free(swp_entry_t); diff --git a/trunk/include/linux/writeback.h b/trunk/include/linux/writeback.h index b096159086e8..64a36ba43b2f 100644 --- a/trunk/include/linux/writeback.h +++ b/trunk/include/linux/writeback.h @@ -53,11 +53,10 @@ struct writeback_control { loff_t start; loff_t end; - unsigned nonblocking:1; /* Don't get stuck on request queues */ - unsigned encountered_congestion:1; /* An output: a queue is full */ - unsigned for_kupdate:1; /* A kupdate writeback */ - unsigned for_reclaim:1; /* Invoked from the page allocator */ - unsigned for_writepages:1; /* This is a writepages() call */ + unsigned nonblocking:1; /* Don't get stuck on request queues */ + unsigned encountered_congestion:1; /* An output: a queue is full */ + unsigned for_kupdate:1; /* A kupdate writeback */ + unsigned for_reclaim:1; /* Invoked from the page allocator */ }; /* diff --git a/trunk/include/scsi/scsi_driver.h b/trunk/include/scsi/scsi_driver.h index 02e26c1672bf..850dfa877fda 100644 --- a/trunk/include/scsi/scsi_driver.h +++ b/trunk/include/scsi/scsi_driver.h @@ -15,6 +15,7 @@ struct scsi_driver { void (*rescan)(struct device *); int (*issue_flush)(struct device *, sector_t *); int (*prepare_flush)(struct request_queue *, struct request *); + void (*end_flush)(struct request_queue *, struct request *); }; #define to_scsi_driver(drv) \ container_of((drv), struct scsi_driver, gendrv) diff --git a/trunk/include/scsi/scsi_host.h b/trunk/include/scsi/scsi_host.h index 230bc55c0bfa..6cbb1982ed03 100644 --- a/trunk/include/scsi/scsi_host.h +++ b/trunk/include/scsi/scsi_host.h @@ -295,12 +295,6 @@ struct scsi_host_template { */ int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int); - /* - * suspend support - */ - int (*resume)(struct scsi_device *); - int (*suspend)(struct scsi_device *); - /* * Name of proc directory */ @@ -398,6 +392,7 @@ struct scsi_host_template { /* * ordered write support */ + unsigned ordered_flush:1; unsigned ordered_tag:1; /* diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index ba42f3793a84..ce737e02c5a2 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -105,6 +105,7 @@ config SWAP config SYSVIPC bool "System V IPC" + depends on MMU ---help--- Inter Process Communication is a suite of library functions and system calls which let processes (running programs) synchronize and @@ -189,7 +190,7 @@ config AUDIT config AUDITSYSCALL bool "Enable system-call auditing support" - depends on AUDIT && (X86 || PPC || PPC64 || S390 || IA64 || UML || SPARC64) + depends on AUDIT && (X86 || PPC || PPC64 || ARCH_S390 || IA64 || UML || SPARC64) default y if SECURITY_SELINUX help Enable low-overhead system-call auditing infrastructure that diff --git a/trunk/init/do_mounts_md.c b/trunk/init/do_mounts_md.c index f6f36806f84a..3fbc3555ce96 100644 --- a/trunk/init/do_mounts_md.c +++ b/trunk/init/do_mounts_md.c @@ -17,7 +17,7 @@ static int __initdata raid_noautodetect, raid_autopart; static struct { int minor; int partitioned; - int level; + int pers; int chunk; char *device_names; } md_setup_args[MAX_MD_DEVS] __initdata; @@ -47,7 +47,7 @@ extern int mdp_major; */ static int __init md_setup(char *str) { - int minor, level, factor, fault, partitioned = 0; + int minor, level, factor, fault, pers, partitioned = 0; char *pername = ""; char *str1; int ent; @@ -78,7 +78,7 @@ static int __init md_setup(char *str) } if (ent >= md_setup_ents) md_setup_ents++; - switch (get_option(&str, &level)) { /* RAID level */ + switch (get_option(&str, &level)) { /* RAID Personality */ case 2: /* could be 0 or -1.. */ if (level == 0 || level == LEVEL_LINEAR) { if (get_option(&str, &factor) != 2 || /* Chunk Size */ @@ -86,12 +86,16 @@ static int __init md_setup(char *str) printk(KERN_WARNING "md: Too few arguments supplied to md=.\n"); return 0; } - md_setup_args[ent].level = level; + md_setup_args[ent].pers = level; md_setup_args[ent].chunk = 1 << (factor+12); - if (level == LEVEL_LINEAR) + if (level == LEVEL_LINEAR) { + pers = LINEAR; pername = "linear"; - else + } else { + pers = RAID0; pername = "raid0"; + } + md_setup_args[ent].pers = pers; break; } /* FALL THROUGH */ @@ -99,7 +103,7 @@ static int __init md_setup(char *str) str = str1; /* FALL THROUGH */ case 0: - md_setup_args[ent].level = LEVEL_NONE; + md_setup_args[ent].pers = 0; pername="super-block"; } @@ -186,10 +190,10 @@ static void __init md_setup_drive(void) continue; } - if (md_setup_args[ent].level != LEVEL_NONE) { + if (md_setup_args[ent].pers) { /* non-persistent */ mdu_array_info_t ainfo; - ainfo.level = md_setup_args[ent].level; + ainfo.level = pers_to_level(md_setup_args[ent].pers); ainfo.size = 0; ainfo.nr_disks =0; ainfo.raid_disks =0; diff --git a/trunk/init/do_mounts_rd.c b/trunk/init/do_mounts_rd.c index c2683fcd792d..c10b08a80982 100644 --- a/trunk/init/do_mounts_rd.c +++ b/trunk/init/do_mounts_rd.c @@ -145,7 +145,7 @@ int __init rd_load_image(char *from) int nblocks, i, disk; char *buf = NULL; unsigned short rotate = 0; -#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) +#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) char rotator[4] = { '|' , '/' , '-' , '\\' }; #endif @@ -237,7 +237,7 @@ int __init rd_load_image(char *from) } sys_read(in_fd, buf, BLOCK_SIZE); sys_write(out_fd, buf, BLOCK_SIZE); -#if !defined(CONFIG_S390) && !defined(CONFIG_PPC_ISERIES) +#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES) if (!(i % 16)) { printk("%c\b", rotator[rotate & 0x3]); rotate++; diff --git a/trunk/init/main.c b/trunk/init/main.c index 2ed3638deec7..54aaf561cf66 100644 --- a/trunk/init/main.c +++ b/trunk/init/main.c @@ -52,7 +52,6 @@ #include #include #include -#include /* * This is one of the first .c files built. Error out early @@ -100,9 +99,6 @@ extern void acpi_early_init(void); #else static inline void acpi_early_init(void) { } #endif -#ifndef CONFIG_DEBUG_RODATA -static inline void mark_rodata_ro(void) { } -#endif #ifdef CONFIG_TC extern void tc_init(void); @@ -712,7 +708,6 @@ static int init(void * unused) */ free_initmem(); unlock_kernel(); - mark_rodata_ro(); system_state = SYSTEM_RUNNING; numa_default_policy(); diff --git a/trunk/ipc/shm.c b/trunk/ipc/shm.c index 0ef4a1cf3e27..587d836d80d9 100644 --- a/trunk/ipc/shm.c +++ b/trunk/ipc/shm.c @@ -157,22 +157,14 @@ static void shm_close (struct vm_area_struct *shmd) static int shm_mmap(struct file * file, struct vm_area_struct * vma) { - int ret; - - ret = shmem_mmap(file, vma); - if (ret == 0) { - vma->vm_ops = &shm_vm_ops; - shm_inc(file->f_dentry->d_inode->i_ino); - } - - return ret; + file_accessed(file); + vma->vm_ops = &shm_vm_ops; + shm_inc(file->f_dentry->d_inode->i_ino); + return 0; } static struct file_operations shm_file_operations = { - .mmap = shm_mmap, -#ifndef CONFIG_MMU - .get_unmapped_area = shmem_get_unmapped_area, -#endif + .mmap = shm_mmap }; static struct vm_operations_struct shm_vm_ops = { diff --git a/trunk/kernel/acct.c b/trunk/kernel/acct.c index 38d57fa6b78f..6312d6bd43e3 100644 --- a/trunk/kernel/acct.c +++ b/trunk/kernel/acct.c @@ -427,7 +427,6 @@ static void do_acct_process(long exitcode, struct file *file) u64 elapsed; u64 run_time; struct timespec uptime; - unsigned long jiffies; /* * First check to see if there is enough free_space to continue @@ -468,12 +467,12 @@ static void do_acct_process(long exitcode, struct file *file) #endif do_div(elapsed, AHZ); ac.ac_btime = xtime.tv_sec - elapsed; - jiffies = cputime_to_jiffies(cputime_add(current->group_leader->utime, - current->signal->utime)); - ac.ac_utime = encode_comp_t(jiffies_to_AHZ(jiffies)); - jiffies = cputime_to_jiffies(cputime_add(current->group_leader->stime, - current->signal->stime)); - ac.ac_stime = encode_comp_t(jiffies_to_AHZ(jiffies)); + ac.ac_utime = encode_comp_t(jiffies_to_AHZ( + current->signal->utime + + current->group_leader->utime)); + ac.ac_stime = encode_comp_t(jiffies_to_AHZ( + current->signal->stime + + current->group_leader->stime)); /* we really need to bite the bullet and change layout */ ac.ac_uid = current->uid; ac.ac_gid = current->gid; @@ -581,8 +580,7 @@ void acct_process(long exitcode) void acct_update_integrals(struct task_struct *tsk) { if (likely(tsk->mm)) { - long delta = - cputime_to_jiffies(tsk->stime) - tsk->acct_stimexpd; + long delta = tsk->stime - tsk->acct_stimexpd; if (delta == 0) return; diff --git a/trunk/kernel/futex.c b/trunk/kernel/futex.c index 5efa2f978032..5e71a6bf6f6b 100644 --- a/trunk/kernel/futex.c +++ b/trunk/kernel/futex.c @@ -356,13 +356,6 @@ static int futex_wake_op(unsigned long uaddr1, unsigned long uaddr2, int nr_wake if (bh1 != bh2) spin_unlock(&bh2->lock); -#ifndef CONFIG_MMU - /* we don't get EFAULT from MMU faults if we don't have an MMU, - * but we might get them from range checking */ - ret = op_ret; - goto out; -#endif - if (unlikely(op_ret != -EFAULT)) { ret = op_ret; goto out; diff --git a/trunk/kernel/irq/manage.c b/trunk/kernel/irq/manage.c index 97d5559997d2..81c49a4d679e 100644 --- a/trunk/kernel/irq/manage.c +++ b/trunk/kernel/irq/manage.c @@ -366,8 +366,6 @@ int request_irq(unsigned int irq, action->next = NULL; action->dev_id = dev_id; - select_smp_affinity(irq); - retval = setup_irq(irq, action); if (retval) kfree(action); diff --git a/trunk/kernel/irq/proc.c b/trunk/kernel/irq/proc.c index 8a64a4844cde..f26e534c6585 100644 --- a/trunk/kernel/irq/proc.c +++ b/trunk/kernel/irq/proc.c @@ -68,9 +68,7 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer, */ cpus_and(tmp, new_value, cpu_online_map); if (cpus_empty(tmp)) - /* Special case for empty set - allow the architecture - code to set default SMP affinity. */ - return select_smp_affinity(irq) ? -EINVAL : full_count; + return -EINVAL; proc_set_irq_affinity(irq, new_value); diff --git a/trunk/kernel/module.c b/trunk/kernel/module.c index 4b06bbad49c2..2ea929d51ad0 100644 --- a/trunk/kernel/module.c +++ b/trunk/kernel/module.c @@ -1854,7 +1854,8 @@ static struct module *load_module(void __user *umod, kfree(args); free_hdr: vfree(hdr); - return ERR_PTR(err); + if (err < 0) return ERR_PTR(err); + else return ptr; truncated: printk(KERN_ERR "Module len %lu truncated\n", len); diff --git a/trunk/kernel/panic.c b/trunk/kernel/panic.c index c5c4ab255834..aabc5f86fa3f 100644 --- a/trunk/kernel/panic.c +++ b/trunk/kernel/panic.c @@ -60,7 +60,7 @@ NORET_TYPE void panic(const char * fmt, ...) long i; static char buf[1024]; va_list args; -#if defined(CONFIG_S390) +#if defined(CONFIG_ARCH_S390) unsigned long caller = (unsigned long) __builtin_return_address(0); #endif @@ -125,7 +125,7 @@ NORET_TYPE void panic(const char * fmt, ...) printk(KERN_EMERG "Press Stop-A (L1-A) to return to the boot prom\n"); } #endif -#if defined(CONFIG_S390) +#if defined(CONFIG_ARCH_S390) disabled_wait(caller); #endif local_irq_enable(); diff --git a/trunk/kernel/power/disk.c b/trunk/kernel/power/disk.c index e24446f8d8cd..027322a564f4 100644 --- a/trunk/kernel/power/disk.c +++ b/trunk/kernel/power/disk.c @@ -24,11 +24,10 @@ extern suspend_disk_method_t pm_disk_mode; -extern int swsusp_shrink_memory(void); extern int swsusp_suspend(void); -extern int swsusp_write(struct pbe *pblist, unsigned int nr_pages); +extern int swsusp_write(void); extern int swsusp_check(void); -extern int swsusp_read(struct pbe **pblist_ptr); +extern int swsusp_read(void); extern void swsusp_close(void); extern int swsusp_resume(void); @@ -74,6 +73,31 @@ static void power_down(suspend_disk_method_t mode) static int in_suspend __nosavedata = 0; +/** + * free_some_memory - Try to free as much memory as possible + * + * ... but do not OOM-kill anyone + * + * Notice: all userland should be stopped at this point, or + * livelock is possible. + */ + +static void free_some_memory(void) +{ + unsigned int i = 0; + unsigned int tmp; + unsigned long pages = 0; + char *p = "-\\|/"; + + printk("Freeing memory... "); + while ((tmp = shrink_all_memory(10000))) { + pages += tmp; + printk("\b%c", p[i++ % 4]); + } + printk("\bdone (%li pages freed)\n", pages); +} + + static inline void platform_finish(void) { if (pm_disk_mode == PM_DISK_PLATFORM) { @@ -103,8 +127,8 @@ static int prepare_processes(void) } /* Free memory before shutting down devices. */ - if (!(error = swsusp_shrink_memory())) - return 0; + free_some_memory(); + return 0; thaw: thaw_processes(); enable_nonboot_cpus(); @@ -152,7 +176,7 @@ int pm_suspend_disk(void) if (in_suspend) { device_resume(); pr_debug("PM: writing image.\n"); - error = swsusp_write(pagedir_nosave, nr_copy_pages); + error = swsusp_write(); if (!error) power_down(pm_disk_mode); else { @@ -223,7 +247,7 @@ static int software_resume(void) pr_debug("PM: Reading swsusp image.\n"); - if ((error = swsusp_read(&pagedir_nosave))) { + if ((error = swsusp_read())) { swsusp_free(); goto Thaw; } @@ -339,55 +363,37 @@ static ssize_t resume_show(struct subsystem * subsys, char *buf) MINOR(swsusp_resume_device)); } -static ssize_t resume_store(struct subsystem *subsys, const char *buf, size_t n) +static ssize_t resume_store(struct subsystem * subsys, const char * buf, size_t n) { + int len; + char *p; unsigned int maj, min; + int error = -EINVAL; dev_t res; - int ret = -EINVAL; - - if (sscanf(buf, "%u:%u", &maj, &min) != 2) - goto out; - - res = MKDEV(maj,min); - if (maj != MAJOR(res) || min != MINOR(res)) - goto out; - down(&pm_sem); - swsusp_resume_device = res; - up(&pm_sem); - printk("Attempting manual resume\n"); - noresume = 0; - software_resume(); - ret = n; -out: - return ret; -} - -power_attr(resume); - -static ssize_t image_size_show(struct subsystem * subsys, char *buf) -{ - return sprintf(buf, "%u\n", image_size); -} - -static ssize_t image_size_store(struct subsystem * subsys, const char * buf, size_t n) -{ - unsigned int size; + p = memchr(buf, '\n', n); + len = p ? p - buf : n; - if (sscanf(buf, "%u", &size) == 1) { - image_size = size; - return n; + if (sscanf(buf, "%u:%u", &maj, &min) == 2) { + res = MKDEV(maj,min); + if (maj == MAJOR(res) && min == MINOR(res)) { + down(&pm_sem); + swsusp_resume_device = res; + up(&pm_sem); + printk("Attempting manual resume\n"); + noresume = 0; + software_resume(); + } } - return -EINVAL; + return error >= 0 ? n : error; } -power_attr(image_size); +power_attr(resume); static struct attribute * g[] = { &disk_attr.attr, &resume_attr.attr, - &image_size_attr.attr, NULL, }; diff --git a/trunk/kernel/power/power.h b/trunk/kernel/power/power.h index 7e8492fd1423..6c042b5ee14b 100644 --- a/trunk/kernel/power/power.h +++ b/trunk/kernel/power/power.h @@ -9,13 +9,19 @@ #define SUSPEND_CONSOLE (MAX_NR_CONSOLES-1) #endif +#define MAX_PBES ((PAGE_SIZE - sizeof(struct new_utsname) \ + - 4 - 3*sizeof(unsigned long) - sizeof(int) \ + - sizeof(void *)) / sizeof(swp_entry_t)) + struct swsusp_info { struct new_utsname uts; u32 version_code; unsigned long num_physpages; int cpus; unsigned long image_pages; - unsigned long pages; + unsigned long pagedir_pages; + suspend_pagedir_t * suspend_pagedir; + swp_entry_t pagedir[MAX_PBES]; } __attribute__((aligned(PAGE_SIZE))); @@ -42,27 +48,25 @@ static struct subsys_attribute _name##_attr = { \ extern struct subsystem power_subsys; +extern int freeze_processes(void); +extern void thaw_processes(void); + extern int pm_prepare_console(void); extern void pm_restore_console(void); + /* References to section boundaries */ extern const void __nosave_begin, __nosave_end; extern unsigned int nr_copy_pages; -extern struct pbe *pagedir_nosave; - -/* Preferred image size in MB (default 500) */ -extern unsigned int image_size; +extern suspend_pagedir_t *pagedir_nosave; +extern suspend_pagedir_t *pagedir_save; extern asmlinkage int swsusp_arch_suspend(void); extern asmlinkage int swsusp_arch_resume(void); -extern unsigned int count_data_pages(void); extern void free_pagedir(struct pbe *pblist); -extern void release_eaten_pages(void); extern struct pbe *alloc_pagedir(unsigned nr_pages, gfp_t gfp_mask, int safe_needed); +extern void create_pbe_list(struct pbe *pblist, unsigned nr_pages); extern void swsusp_free(void); extern int alloc_data_pages(struct pbe *pblist, gfp_t gfp_mask, int safe_needed); -extern unsigned int snapshot_nr_pages(void); -extern struct pbe *snapshot_pblist(void); -extern void snapshot_pblist_set(struct pbe *pblist); diff --git a/trunk/kernel/power/snapshot.c b/trunk/kernel/power/snapshot.c index 41f66365f0d8..4a6dbcefd378 100644 --- a/trunk/kernel/power/snapshot.c +++ b/trunk/kernel/power/snapshot.c @@ -33,35 +33,7 @@ #include "power.h" -struct pbe *pagedir_nosave; -unsigned int nr_copy_pages; - #ifdef CONFIG_HIGHMEM -unsigned int count_highmem_pages(void) -{ - struct zone *zone; - unsigned long zone_pfn; - unsigned int n = 0; - - for_each_zone (zone) - if (is_highmem(zone)) { - mark_free_pages(zone); - for (zone_pfn = 0; zone_pfn < zone->spanned_pages; zone_pfn++) { - struct page *page; - unsigned long pfn = zone_pfn + zone->zone_start_pfn; - if (!pfn_valid(pfn)) - continue; - page = pfn_to_page(pfn); - if (PageReserved(page)) - continue; - if (PageNosaveFree(page)) - continue; - n++; - } - } - return n; -} - struct highmem_page { char *data; struct page *page; @@ -177,15 +149,17 @@ static int saveable(struct zone *zone, unsigned long *zone_pfn) BUG_ON(PageReserved(page) && PageNosave(page)); if (PageNosave(page)) return 0; - if (PageReserved(page) && pfn_is_nosave(pfn)) + if (PageReserved(page) && pfn_is_nosave(pfn)) { + pr_debug("[nosave pfn 0x%lx]", pfn); return 0; + } if (PageNosaveFree(page)) return 0; return 1; } -unsigned int count_data_pages(void) +static unsigned count_data_pages(void) { struct zone *zone; unsigned long zone_pfn; @@ -270,7 +244,7 @@ static inline void fill_pb_page(struct pbe *pbpage) * of memory pages allocated with alloc_pagedir() */ -static inline void create_pbe_list(struct pbe *pblist, unsigned int nr_pages) +void create_pbe_list(struct pbe *pblist, unsigned int nr_pages) { struct pbe *pbpage, *p; unsigned int num = PBES_PER_PAGE; @@ -287,35 +261,7 @@ static inline void create_pbe_list(struct pbe *pblist, unsigned int nr_pages) p->next = p + 1; p->next = NULL; } -} - -/** - * On resume it is necessary to trace and eventually free the unsafe - * pages that have been allocated, because they are needed for I/O - * (on x86-64 we likely will "eat" these pages once again while - * creating the temporary page translation tables) - */ - -struct eaten_page { - struct eaten_page *next; - char padding[PAGE_SIZE - sizeof(void *)]; -}; - -static struct eaten_page *eaten_pages = NULL; - -void release_eaten_pages(void) -{ - struct eaten_page *p, *q; - - p = eaten_pages; - while (p) { - q = p->next; - /* We don't want swsusp_free() to free this page again */ - ClearPageNosave(virt_to_page(p)); - free_page((unsigned long)p); - p = q; - } - eaten_pages = NULL; + pr_debug("create_pbe_list(): initialized %d PBEs\n", num); } /** @@ -336,12 +282,9 @@ static inline void *alloc_image_page(gfp_t gfp_mask, int safe_needed) if (safe_needed) do { res = (void *)get_zeroed_page(gfp_mask); - if (res && PageNosaveFree(virt_to_page(res))) { + if (res && PageNosaveFree(virt_to_page(res))) /* This is for swsusp_free() */ SetPageNosave(virt_to_page(res)); - ((struct eaten_page *)res)->next = eaten_pages; - eaten_pages = res; - } } while (res && PageNosaveFree(virt_to_page(res))); else res = (void *)get_zeroed_page(gfp_mask); @@ -389,8 +332,7 @@ struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed if (!pbe) { /* get_zeroed_page() failed */ free_pagedir(pblist); pblist = NULL; - } else - create_pbe_list(pblist, nr_pages); + } return pblist; } @@ -428,14 +370,8 @@ void swsusp_free(void) static int enough_free_mem(unsigned int nr_pages) { - struct zone *zone; - unsigned int n = 0; - - for_each_zone (zone) - if (!is_highmem(zone)) - n += zone->free_pages; - pr_debug("swsusp: available memory: %u pages\n", n); - return n > (nr_pages + PAGES_FOR_IO + + pr_debug("swsusp: available memory: %u pages\n", nr_free_pages()); + return nr_free_pages() > (nr_pages + PAGES_FOR_IO + (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); } @@ -459,6 +395,7 @@ static struct pbe *swsusp_alloc(unsigned int nr_pages) printk(KERN_ERR "suspend: Allocating pagedir failed.\n"); return NULL; } + create_pbe_list(pblist, nr_pages); if (alloc_data_pages(pblist, GFP_ATOMIC | __GFP_COLD, 0)) { printk(KERN_ERR "suspend: Allocating image pages failed.\n"); @@ -484,6 +421,10 @@ asmlinkage int swsusp_save(void) (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE, PAGES_FOR_IO, nr_free_pages()); + /* This is needed because of the fixed size of swsusp_info */ + if (MAX_PBES < (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE) + return -ENOSPC; + if (!enough_free_mem(nr_pages)) { printk(KERN_ERR "swsusp: Not enough free memory\n"); return -ENOMEM; diff --git a/trunk/kernel/power/swsusp.c b/trunk/kernel/power/swsusp.c index 55a18d26abed..c05f46e7348f 100644 --- a/trunk/kernel/power/swsusp.c +++ b/trunk/kernel/power/swsusp.c @@ -30,8 +30,8 @@ * Alex Badea : * Fixed runaway init * - * Rafael J. Wysocki - * Added the swap map data structure and reworked the handling of swap + * Andreas Steinmetz : + * Added encrypted suspend option * * More state savers are welcome. Especially for the scsi layer... * @@ -67,33 +67,44 @@ #include #include -#include "power.h" +#include +#include +#include -/* - * Preferred image size in MB (tunable via /sys/power/image_size). - * When it is set to N, swsusp will do its best to ensure the image - * size will not exceed N MB, but if that is impossible, it will - * try to create the smallest image possible. - */ -unsigned int image_size = 500; +#include "power.h" #ifdef CONFIG_HIGHMEM -unsigned int count_highmem_pages(void); int save_highmem(void); int restore_highmem(void); #else static int save_highmem(void) { return 0; } static int restore_highmem(void) { return 0; } -static unsigned int count_highmem_pages(void) { return 0; } #endif +#define CIPHER "aes" +#define MAXKEY 32 +#define MAXIV 32 + extern char resume_file[]; +/* Local variables that should not be affected by save */ +unsigned int nr_copy_pages __nosavedata = 0; + +/* Suspend pagedir is allocated before final copy, therefore it + must be freed after resume + + Warning: this is even more evil than it seems. Pagedirs this file + talks about are completely different from page directories used by + MMU hardware. + */ +suspend_pagedir_t *pagedir_nosave __nosavedata = NULL; + #define SWSUSP_SIG "S1SUSPEND" static struct swsusp_header { - char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)]; - swp_entry_t image; + char reserved[PAGE_SIZE - 20 - MAXKEY - MAXIV - sizeof(swp_entry_t)]; + u8 key_iv[MAXKEY+MAXIV]; + swp_entry_t swsusp_info; char orig_sig[10]; char sig[10]; } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; @@ -104,9 +115,140 @@ static struct swsusp_info swsusp_info; * Saving part... */ -static unsigned short root_swap = 0xffff; +/* We memorize in swapfile_used what swap devices are used for suspension */ +#define SWAPFILE_UNUSED 0 +#define SWAPFILE_SUSPEND 1 /* This is the suspending device */ +#define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */ + +static unsigned short swapfile_used[MAX_SWAPFILES]; +static unsigned short root_swap; + +static int write_page(unsigned long addr, swp_entry_t *loc); +static int bio_read_page(pgoff_t page_off, void *page); + +static u8 key_iv[MAXKEY+MAXIV]; + +#ifdef CONFIG_SWSUSP_ENCRYPT + +static int crypto_init(int mode, void **mem) +{ + int error = 0; + int len; + char *modemsg; + struct crypto_tfm *tfm; + + modemsg = mode ? "suspend not possible" : "resume not possible"; + + tfm = crypto_alloc_tfm(CIPHER, CRYPTO_TFM_MODE_CBC); + if(!tfm) { + printk(KERN_ERR "swsusp: no tfm, %s\n", modemsg); + error = -EINVAL; + goto out; + } + + if(MAXKEY < crypto_tfm_alg_min_keysize(tfm)) { + printk(KERN_ERR "swsusp: key buffer too small, %s\n", modemsg); + error = -ENOKEY; + goto fail; + } + + if (mode) + get_random_bytes(key_iv, MAXKEY+MAXIV); + + len = crypto_tfm_alg_max_keysize(tfm); + if (len > MAXKEY) + len = MAXKEY; + + if (crypto_cipher_setkey(tfm, key_iv, len)) { + printk(KERN_ERR "swsusp: key setup failure, %s\n", modemsg); + error = -EKEYREJECTED; + goto fail; + } + + len = crypto_tfm_alg_ivsize(tfm); + + if (MAXIV < len) { + printk(KERN_ERR "swsusp: iv buffer too small, %s\n", modemsg); + error = -EOVERFLOW; + goto fail; + } + + crypto_cipher_set_iv(tfm, key_iv+MAXKEY, len); + + *mem=(void *)tfm; + + goto out; + +fail: crypto_free_tfm(tfm); +out: return error; +} + +static __inline__ void crypto_exit(void *mem) +{ + crypto_free_tfm((struct crypto_tfm *)mem); +} + +static __inline__ int crypto_write(struct pbe *p, void *mem) +{ + int error = 0; + struct scatterlist src, dst; + + src.page = virt_to_page(p->address); + src.offset = 0; + src.length = PAGE_SIZE; + dst.page = virt_to_page((void *)&swsusp_header); + dst.offset = 0; + dst.length = PAGE_SIZE; + + error = crypto_cipher_encrypt((struct crypto_tfm *)mem, &dst, &src, + PAGE_SIZE); + + if (!error) + error = write_page((unsigned long)&swsusp_header, + &(p->swap_address)); + return error; +} + +static __inline__ int crypto_read(struct pbe *p, void *mem) +{ + int error = 0; + struct scatterlist src, dst; + + error = bio_read_page(swp_offset(p->swap_address), (void *)p->address); + if (!error) { + src.offset = 0; + src.length = PAGE_SIZE; + dst.offset = 0; + dst.length = PAGE_SIZE; + src.page = dst.page = virt_to_page((void *)p->address); + + error = crypto_cipher_decrypt((struct crypto_tfm *)mem, &dst, + &src, PAGE_SIZE); + } + return error; +} +#else +static __inline__ int crypto_init(int mode, void *mem) +{ + return 0; +} + +static __inline__ void crypto_exit(void *mem) +{ +} + +static __inline__ int crypto_write(struct pbe *p, void *mem) +{ + return write_page(p->address, &(p->swap_address)); +} -static int mark_swapfiles(swp_entry_t start) +static __inline__ int crypto_read(struct pbe *p, void *mem) +{ + return bio_read_page(swp_offset(p->swap_address), (void *)p->address); +} +#endif + +static int mark_swapfiles(swp_entry_t prev) { int error; @@ -117,7 +259,8 @@ static int mark_swapfiles(swp_entry_t start) !memcmp("SWAPSPACE2",swsusp_header.sig, 10)) { memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10); memcpy(swsusp_header.sig,SWSUSP_SIG, 10); - swsusp_header.image = start; + memcpy(swsusp_header.key_iv, key_iv, MAXKEY+MAXIV); + swsusp_header.swsusp_info = prev; error = rw_swap_page_sync(WRITE, swp_entry(root_swap, 0), virt_to_page((unsigned long) @@ -140,7 +283,7 @@ static int mark_swapfiles(swp_entry_t start) * devfs, since the resume code can only recognize the form /dev/hda4, * but the suspend code would see the long name.) */ -static inline int is_resume_device(const struct swap_info_struct *swap_info) +static int is_resume_device(const struct swap_info_struct *swap_info) { struct file *file = swap_info->swap_file; struct inode *inode = file->f_dentry->d_inode; @@ -151,22 +294,54 @@ static inline int is_resume_device(const struct swap_info_struct *swap_info) static int swsusp_swap_check(void) /* This is called before saving image */ { - int i; + int i, len; + + len=strlen(resume_file); + root_swap = 0xFFFF; - if (!swsusp_resume_device) - return -ENODEV; spin_lock(&swap_lock); - for (i = 0; i < MAX_SWAPFILES; i++) { - if (!(swap_info[i].flags & SWP_WRITEOK)) - continue; - if (is_resume_device(swap_info + i)) { - spin_unlock(&swap_lock); - root_swap = i; - return 0; + for (i=0; inext; - free_page((unsigned long)swap_map); - swap_map = swp; - } -} - -static struct swap_map_page *alloc_swap_map(unsigned int nr_pages) -{ - struct swap_map_page *swap_map, *swp; - unsigned n = 0; - - if (!nr_pages) - return NULL; - - pr_debug("alloc_swap_map(): nr_pages = %d\n", nr_pages); - swap_map = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC); - swp = swap_map; - for (n = MAP_PAGE_SIZE; n < nr_pages; n += MAP_PAGE_SIZE) { - swp->next = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC); - swp = swp->next; - if (!swp) { - free_swap_map(swap_map); - return NULL; - } - } - return swap_map; -} - -/** - * reverse_swap_map - reverse the order of pages in the swap map - * @swap_map - */ - -static inline struct swap_map_page *reverse_swap_map(struct swap_map_page *swap_map) -{ - struct swap_map_page *prev, *next; - - prev = NULL; - while (swap_map) { - next = swap_map->next; - swap_map->next = prev; - prev = swap_map; - swap_map = next; - } - return prev; -} - -/** - * free_swap_map_entries - free the swap entries allocated to store - * the swap map @swap_map (this is only called in case of an error) + * Walk the list of used swap entries and free each one. + * This is only used for cleanup when suspend fails. */ -static inline void free_swap_map_entries(struct swap_map_page *swap_map) -{ - while (swap_map) { - if (swap_map->next_swap.val) - swap_free(swap_map->next_swap); - swap_map = swap_map->next; - } -} - -/** - * save_swap_map - save the swap map used for tracing the data pages - * stored in the swap - */ - -static int save_swap_map(struct swap_map_page *swap_map, swp_entry_t *start) -{ - swp_entry_t entry = (swp_entry_t){0}; - int error; - - while (swap_map) { - swap_map->next_swap = entry; - if ((error = write_page((unsigned long)swap_map, &entry))) - return error; - swap_map = swap_map->next; - } - *start = entry; - return 0; -} - -/** - * free_image_entries - free the swap entries allocated to store - * the image data pages (this is only called in case of an error) - */ - -static inline void free_image_entries(struct swap_map_page *swp) +static void data_free(void) { - unsigned k; + swp_entry_t entry; + struct pbe *p; - while (swp) { - for (k = 0; k < MAP_PAGE_SIZE; k++) - if (swp->entries[k].val) - swap_free(swp->entries[k]); - swp = swp->next; + for_each_pbe (p, pagedir_nosave) { + entry = p->swap_address; + if (entry.val) + swap_free(entry); + else + break; } } /** - * The swap_map_handle structure is used for handling the swap map in - * a file-alike way + * data_write - Write saved image to swap. + * + * Walk the list of pages in the image and sync each one to swap. */ - -struct swap_map_handle { - struct swap_map_page *cur; - unsigned int k; -}; - -static inline void init_swap_map_handle(struct swap_map_handle *handle, - struct swap_map_page *map) +static int data_write(void) { - handle->cur = map; - handle->k = 0; -} - -static inline int swap_map_write_page(struct swap_map_handle *handle, - unsigned long addr) -{ - int error; + int error = 0, i = 0; + unsigned int mod = nr_copy_pages / 100; + struct pbe *p; + void *tfm; - error = write_page(addr, handle->cur->entries + handle->k); - if (error) + if ((error = crypto_init(1, &tfm))) return error; - if (++handle->k >= MAP_PAGE_SIZE) { - handle->cur = handle->cur->next; - handle->k = 0; - } - return 0; -} - -/** - * save_image_data - save the data pages pointed to by the PBEs - * from the list @pblist using the swap map handle @handle - * (assume there are @nr_pages data pages to save) - */ -static int save_image_data(struct pbe *pblist, - struct swap_map_handle *handle, - unsigned int nr_pages) -{ - unsigned int m; - struct pbe *p; - int error = 0; + if (!mod) + mod = 1; - printk("Saving image data pages (%u pages) ... ", nr_pages); - m = nr_pages / 100; - if (!m) - m = 1; - nr_pages = 0; - for_each_pbe (p, pblist) { - error = swap_map_write_page(handle, p->address); - if (error) - break; - if (!(nr_pages % m)) - printk("\b\b\b\b%3d%%", nr_pages / m); - nr_pages++; + printk( "Writing data to swap (%d pages)... ", nr_copy_pages ); + for_each_pbe (p, pagedir_nosave) { + if (!(i%mod)) + printk( "\b\b\b\b%3d%%", i / mod ); + if ((error = crypto_write(p, tfm))) { + crypto_exit(tfm); + return error; + } + i++; } - if (!error) - printk("\b\b\b\bdone\n"); + printk("\b\b\b\bdone\n"); + crypto_exit(tfm); return error; } @@ -410,70 +440,70 @@ static void dump_info(void) pr_debug(" swsusp: UTS Domain: %s\n",swsusp_info.uts.domainname); pr_debug(" swsusp: CPUs: %d\n",swsusp_info.cpus); pr_debug(" swsusp: Image: %ld Pages\n",swsusp_info.image_pages); - pr_debug(" swsusp: Total: %ld Pages\n", swsusp_info.pages); + pr_debug(" swsusp: Pagedir: %ld Pages\n",swsusp_info.pagedir_pages); } -static void init_header(unsigned int nr_pages) +static void init_header(void) { memset(&swsusp_info, 0, sizeof(swsusp_info)); swsusp_info.version_code = LINUX_VERSION_CODE; swsusp_info.num_physpages = num_physpages; memcpy(&swsusp_info.uts, &system_utsname, sizeof(system_utsname)); + swsusp_info.suspend_pagedir = pagedir_nosave; swsusp_info.cpus = num_online_cpus(); - swsusp_info.image_pages = nr_pages; - swsusp_info.pages = nr_pages + - ((nr_pages * sizeof(long) + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1; + swsusp_info.image_pages = nr_copy_pages; +} + +static int close_swap(void) +{ + swp_entry_t entry; + int error; + + dump_info(); + error = write_page((unsigned long)&swsusp_info, &entry); + if (!error) { + printk( "S" ); + error = mark_swapfiles(entry); + printk( "|\n" ); + } + return error; } /** - * pack_orig_addresses - the .orig_address fields of the PBEs from the - * list starting at @pbe are stored in the array @buf[] (1 page) + * free_pagedir_entries - Free pages used by the page directory. + * + * This is used during suspend for error recovery. */ -static inline struct pbe *pack_orig_addresses(unsigned long *buf, - struct pbe *pbe) +static void free_pagedir_entries(void) { - int j; + int i; - for (j = 0; j < PAGE_SIZE / sizeof(long) && pbe; j++) { - buf[j] = pbe->orig_address; - pbe = pbe->next; - } - if (!pbe) - for (; j < PAGE_SIZE / sizeof(long); j++) - buf[j] = 0; - return pbe; + for (i = 0; i < swsusp_info.pagedir_pages; i++) + swap_free(swsusp_info.pagedir[i]); } + /** - * save_image_metadata - save the .orig_address fields of the PBEs - * from the list @pblist using the swap map handle @handle + * write_pagedir - Write the array of pages holding the page directory. + * @last: Last swap entry we write (needed for header). */ -static int save_image_metadata(struct pbe *pblist, - struct swap_map_handle *handle) +static int write_pagedir(void) { - unsigned long *buf; - unsigned int n = 0; - struct pbe *p; int error = 0; + unsigned int n = 0; + struct pbe *pbe; - printk("Saving image metadata ... "); - buf = (unsigned long *)get_zeroed_page(GFP_ATOMIC); - if (!buf) - return -ENOMEM; - p = pblist; - while (p) { - p = pack_orig_addresses(buf, p); - error = swap_map_write_page(handle, (unsigned long)buf); - if (error) - break; - n++; + printk( "Writing pagedir..."); + for_each_pb_page (pbe, pagedir_nosave) { + if ((error = write_page((unsigned long)pbe, &swsusp_info.pagedir[n++]))) + return error; } - free_page((unsigned long)buf); - if (!error) - printk("done (%u pages saved)\n", n); + + swsusp_info.pagedir_pages = n; + printk("done (%u pages)\n", n); return error; } @@ -481,126 +511,76 @@ static int save_image_metadata(struct pbe *pblist, * enough_swap - Make sure we have enough swap to save the image. * * Returns TRUE or FALSE after checking the total amount of swap - * space avaiable from the resume partition. + * space avaiable. + * + * FIXME: si_swapinfo(&i) returns all swap devices information. + * We should only consider resume_device. */ static int enough_swap(unsigned int nr_pages) { - unsigned int free_swap = swap_info[root_swap].pages - - swap_info[root_swap].inuse_pages; + struct sysinfo i; - pr_debug("swsusp: free swap pages: %u\n", free_swap); - return free_swap > (nr_pages + PAGES_FOR_IO + + si_swapinfo(&i); + pr_debug("swsusp: available swap: %lu pages\n", i.freeswap); + return i.freeswap > (nr_pages + PAGES_FOR_IO + (nr_pages + PBES_PER_PAGE - 1) / PBES_PER_PAGE); } /** - * swsusp_write - Write entire image and metadata. + * write_suspend_image - Write entire image and metadata. * - * It is important _NOT_ to umount filesystems at this point. We want - * them synced (in case something goes wrong) but we DO not want to mark - * filesystem clean: it is not. (And it does not matter, if we resume - * correctly, we'll mark system clean, anyway.) */ - -int swsusp_write(struct pbe *pblist, unsigned int nr_pages) +static int write_suspend_image(void) { - struct swap_map_page *swap_map; - struct swap_map_handle handle; - swp_entry_t start; int error; - if ((error = swsusp_swap_check())) { - printk(KERN_ERR "swsusp: Cannot find swap device, try swapon -a.\n"); - return error; - } - if (!enough_swap(nr_pages)) { + if (!enough_swap(nr_copy_pages)) { printk(KERN_ERR "swsusp: Not enough free swap\n"); return -ENOSPC; } - init_header(nr_pages); - swap_map = alloc_swap_map(swsusp_info.pages); - if (!swap_map) - return -ENOMEM; - init_swap_map_handle(&handle, swap_map); - - error = swap_map_write_page(&handle, (unsigned long)&swsusp_info); - if (!error) - error = save_image_metadata(pblist, &handle); - if (!error) - error = save_image_data(pblist, &handle, nr_pages); - if (error) - goto Free_image_entries; + init_header(); + if ((error = data_write())) + goto FreeData; - swap_map = reverse_swap_map(swap_map); - error = save_swap_map(swap_map, &start); - if (error) - goto Free_map_entries; + if ((error = write_pagedir())) + goto FreePagedir; - dump_info(); - printk( "S" ); - error = mark_swapfiles(start); - printk( "|\n" ); - if (error) - goto Free_map_entries; - -Free_swap_map: - free_swap_map(swap_map); + if ((error = close_swap())) + goto FreePagedir; + Done: + memset(key_iv, 0, MAXKEY+MAXIV); return error; - -Free_map_entries: - free_swap_map_entries(swap_map); -Free_image_entries: - free_image_entries(swap_map); - goto Free_swap_map; + FreePagedir: + free_pagedir_entries(); + FreeData: + data_free(); + goto Done; } -/** - * swsusp_shrink_memory - Try to free as much memory as needed - * - * ... but do not OOM-kill anyone - * - * Notice: all userland should be stopped before it is called, or - * livelock is possible. +/* It is important _NOT_ to umount filesystems at this point. We want + * them synced (in case something goes wrong) but we DO not want to mark + * filesystem clean: it is not. (And it does not matter, if we resume + * correctly, we'll mark system clean, anyway.) */ - -#define SHRINK_BITE 10000 - -int swsusp_shrink_memory(void) +int swsusp_write(void) { - long size, tmp; - struct zone *zone; - unsigned long pages = 0; - unsigned int i = 0; - char *p = "-\\|/"; - - printk("Shrinking memory... "); - do { - size = 2 * count_highmem_pages(); - size += size / 50 + count_data_pages(); - size += (size + PBES_PER_PAGE - 1) / PBES_PER_PAGE + - PAGES_FOR_IO; - tmp = size; - for_each_zone (zone) - if (!is_highmem(zone)) - tmp -= zone->free_pages; - if (tmp > 0) { - tmp = shrink_all_memory(SHRINK_BITE); - if (!tmp) - return -ENOMEM; - pages += tmp; - } else if (size > (image_size * 1024 * 1024) / PAGE_SIZE) { - tmp = shrink_all_memory(SHRINK_BITE); - pages += tmp; - } - printk("\b%c", p[i++%4]); - } while (tmp > 0); - printk("\bdone (%lu pages freed)\n", pages); + int error; - return 0; + if ((error = swsusp_swap_check())) { + printk(KERN_ERR "swsusp: cannot find swap device, try swapon -a.\n"); + return error; + } + lock_swapdevices(); + error = write_suspend_image(); + /* This will unlock ignored swap devices since writing is finished */ + lock_swapdevices(); + return error; } + + int swsusp_suspend(void) { int error; @@ -697,6 +677,7 @@ static void copy_page_backup_list(struct pbe *dst, struct pbe *src) /* We assume both lists contain the same number of elements */ while (src) { dst->orig_address = src->orig_address; + dst->swap_address = src->swap_address; dst = dst->next; src = src->next; } @@ -776,224 +757,198 @@ static int bio_write_page(pgoff_t page_off, void *page) return submit(WRITE, page_off, page); } -/** - * The following functions allow us to read data using a swap map - * in a file-alike way +/* + * Sanity check if this image makes sense with this kernel/swap context + * I really don't think that it's foolproof but more than nothing.. */ -static inline void release_swap_map_reader(struct swap_map_handle *handle) +static const char *sanity_check(void) { - if (handle->cur) - free_page((unsigned long)handle->cur); - handle->cur = NULL; + dump_info(); + if (swsusp_info.version_code != LINUX_VERSION_CODE) + return "kernel version"; + if (swsusp_info.num_physpages != num_physpages) + return "memory size"; + if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) + return "system type"; + if (strcmp(swsusp_info.uts.release,system_utsname.release)) + return "kernel release"; + if (strcmp(swsusp_info.uts.version,system_utsname.version)) + return "version"; + if (strcmp(swsusp_info.uts.machine,system_utsname.machine)) + return "machine"; +#if 0 + /* We can't use number of online CPUs when we use hotplug to remove them ;-))) */ + if (swsusp_info.cpus != num_possible_cpus()) + return "number of cpus"; +#endif + return NULL; } -static inline int get_swap_map_reader(struct swap_map_handle *handle, - swp_entry_t start) + +static int check_header(void) { + const char *reason = NULL; int error; - if (!swp_offset(start)) - return -EINVAL; - handle->cur = (struct swap_map_page *)get_zeroed_page(GFP_ATOMIC); - if (!handle->cur) - return -ENOMEM; - error = bio_read_page(swp_offset(start), handle->cur); - if (error) { - release_swap_map_reader(handle); + if ((error = bio_read_page(swp_offset(swsusp_header.swsusp_info), &swsusp_info))) return error; + + /* Is this same machine? */ + if ((reason = sanity_check())) { + printk(KERN_ERR "swsusp: Resume mismatch: %s\n",reason); + return -EPERM; } - handle->k = 0; - return 0; + nr_copy_pages = swsusp_info.image_pages; + return error; } -static inline int swap_map_read_page(struct swap_map_handle *handle, void *buf) +static int check_sig(void) { - unsigned long offset; int error; - if (!handle->cur) - return -EINVAL; - offset = swp_offset(handle->cur->entries[handle->k]); - if (!offset) - return -EINVAL; - error = bio_read_page(offset, buf); - if (error) + memset(&swsusp_header, 0, sizeof(swsusp_header)); + if ((error = bio_read_page(0, &swsusp_header))) return error; - if (++handle->k >= MAP_PAGE_SIZE) { - handle->k = 0; - offset = swp_offset(handle->cur->next_swap); - if (!offset) - release_swap_map_reader(handle); - else - error = bio_read_page(offset, handle->cur); + if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { + memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); + memcpy(key_iv, swsusp_header.key_iv, MAXKEY+MAXIV); + memset(swsusp_header.key_iv, 0, MAXKEY+MAXIV); + + /* + * Reset swap signature now. + */ + error = bio_write_page(0, &swsusp_header); + } else { + return -EINVAL; } + if (!error) + pr_debug("swsusp: Signature found, resuming\n"); return error; } -static int check_header(void) -{ - char *reason = NULL; - - dump_info(); - if (swsusp_info.version_code != LINUX_VERSION_CODE) - reason = "kernel version"; - if (swsusp_info.num_physpages != num_physpages) - reason = "memory size"; - if (strcmp(swsusp_info.uts.sysname,system_utsname.sysname)) - reason = "system type"; - if (strcmp(swsusp_info.uts.release,system_utsname.release)) - reason = "kernel release"; - if (strcmp(swsusp_info.uts.version,system_utsname.version)) - reason = "version"; - if (strcmp(swsusp_info.uts.machine,system_utsname.machine)) - reason = "machine"; - if (reason) { - printk(KERN_ERR "swsusp: Resume mismatch: %s\n", reason); - return -EPERM; - } - return 0; -} - /** - * load_image_data - load the image data using the swap map handle - * @handle and store them using the page backup list @pblist - * (assume there are @nr_pages pages to load) + * data_read - Read image pages from swap. + * + * You do not need to check for overlaps, check_pagedir() + * already did that. */ -static int load_image_data(struct pbe *pblist, - struct swap_map_handle *handle, - unsigned int nr_pages) +static int data_read(struct pbe *pblist) { - int error; - unsigned int m; struct pbe *p; + int error = 0; + int i = 0; + int mod = swsusp_info.image_pages / 100; + void *tfm; - if (!pblist) - return -EINVAL; - printk("Loading image data pages (%u pages) ... ", nr_pages); - m = nr_pages / 100; - if (!m) - m = 1; - nr_pages = 0; - p = pblist; - while (p) { - error = swap_map_read_page(handle, (void *)p->address); - if (error) - break; - p = p->next; - if (!(nr_pages % m)) - printk("\b\b\b\b%3d%%", nr_pages / m); - nr_pages++; + if ((error = crypto_init(0, &tfm))) + return error; + + if (!mod) + mod = 1; + + printk("swsusp: Reading image data (%lu pages): ", + swsusp_info.image_pages); + + for_each_pbe (p, pblist) { + if (!(i % mod)) + printk("\b\b\b\b%3d%%", i / mod); + + if ((error = crypto_read(p, tfm))) { + crypto_exit(tfm); + return error; + } + + i++; } - if (!error) - printk("\b\b\b\bdone\n"); + printk("\b\b\b\bdone\n"); + crypto_exit(tfm); return error; } /** - * unpack_orig_addresses - copy the elements of @buf[] (1 page) to - * the PBEs in the list starting at @pbe + * read_pagedir - Read page backup list pages from swap */ -static inline struct pbe *unpack_orig_addresses(unsigned long *buf, - struct pbe *pbe) +static int read_pagedir(struct pbe *pblist) { - int j; + struct pbe *pbpage, *p; + unsigned int i = 0; + int error; - for (j = 0; j < PAGE_SIZE / sizeof(long) && pbe; j++) { - pbe->orig_address = buf[j]; - pbe = pbe->next; - } - return pbe; -} + if (!pblist) + return -EFAULT; -/** - * load_image_metadata - load the image metadata using the swap map - * handle @handle and put them into the PBEs in the list @pblist - */ + printk("swsusp: Reading pagedir (%lu pages)\n", + swsusp_info.pagedir_pages); -static int load_image_metadata(struct pbe *pblist, struct swap_map_handle *handle) -{ - struct pbe *p; - unsigned long *buf; - unsigned int n = 0; - int error = 0; + for_each_pb_page (pbpage, pblist) { + unsigned long offset = swp_offset(swsusp_info.pagedir[i++]); - printk("Loading image metadata ... "); - buf = (unsigned long *)get_zeroed_page(GFP_ATOMIC); - if (!buf) - return -ENOMEM; - p = pblist; - while (p) { - error = swap_map_read_page(handle, buf); + error = -EFAULT; + if (offset) { + p = (pbpage + PB_PAGE_SKIP)->next; + error = bio_read_page(offset, (void *)pbpage); + (pbpage + PB_PAGE_SKIP)->next = p; + } if (error) break; - p = unpack_orig_addresses(buf, p); - n++; } - free_page((unsigned long)buf); + if (!error) - printk("done (%u pages loaded)\n", n); + BUG_ON(i != swsusp_info.pagedir_pages); + return error; } -int swsusp_read(struct pbe **pblist_ptr) + +static int check_suspend_image(void) { - int error; - struct pbe *p, *pblist; - struct swap_map_handle handle; - unsigned int nr_pages; + int error = 0; - if (IS_ERR(resume_bdev)) { - pr_debug("swsusp: block device not initialised\n"); - return PTR_ERR(resume_bdev); - } + if ((error = check_sig())) + return error; - error = get_swap_map_reader(&handle, swsusp_header.image); - if (!error) - error = swap_map_read_page(&handle, &swsusp_info); - if (!error) - error = check_header(); - if (error) + if ((error = check_header())) return error; - nr_pages = swsusp_info.image_pages; - p = alloc_pagedir(nr_pages, GFP_ATOMIC, 0); - if (!p) + + return 0; +} + +static int read_suspend_image(void) +{ + int error = 0; + struct pbe *p; + + if (!(p = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 0))) return -ENOMEM; - error = load_image_metadata(p, &handle); - if (!error) { - mark_unsafe_pages(p); - pblist = alloc_pagedir(nr_pages, GFP_ATOMIC, 1); - if (pblist) - copy_page_backup_list(pblist, p); - free_pagedir(p); - if (!pblist) - error = -ENOMEM; - - /* Allocate memory for the image and read the data from swap */ - if (!error) - error = alloc_data_pages(pblist, GFP_ATOMIC, 1); - if (!error) { - release_eaten_pages(); - error = load_image_data(pblist, &handle, nr_pages); - } - if (!error) - *pblist_ptr = pblist; + + if ((error = read_pagedir(p))) + return error; + create_pbe_list(p, nr_copy_pages); + mark_unsafe_pages(p); + pagedir_nosave = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1); + if (pagedir_nosave) { + create_pbe_list(pagedir_nosave, nr_copy_pages); + copy_page_backup_list(pagedir_nosave, p); } - release_swap_map_reader(&handle); + free_pagedir(p); + if (!pagedir_nosave) + return -ENOMEM; - blkdev_put(resume_bdev); + /* Allocate memory for the image and read the data from swap */ + + error = alloc_data_pages(pagedir_nosave, GFP_ATOMIC, 1); if (!error) - pr_debug("swsusp: Reading resume file was successful\n"); - else - pr_debug("swsusp: Error %d resuming\n", error); + error = data_read(pagedir_nosave); + return error; } /** - * swsusp_check - Check for swsusp signature in the resume device + * swsusp_check - Check for saved image in swap */ int swsusp_check(void) @@ -1003,27 +958,40 @@ int swsusp_check(void) resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ); if (!IS_ERR(resume_bdev)) { set_blocksize(resume_bdev, PAGE_SIZE); - memset(&swsusp_header, 0, sizeof(swsusp_header)); - if ((error = bio_read_page(0, &swsusp_header))) - return error; - if (!memcmp(SWSUSP_SIG, swsusp_header.sig, 10)) { - memcpy(swsusp_header.sig, swsusp_header.orig_sig, 10); - /* Reset swap signature now */ - error = bio_write_page(0, &swsusp_header); - } else { - return -EINVAL; - } + error = check_suspend_image(); if (error) - blkdev_put(resume_bdev); - else - pr_debug("swsusp: Signature found, resuming\n"); - } else { + blkdev_put(resume_bdev); + } else error = PTR_ERR(resume_bdev); - } - if (error) + if (!error) + pr_debug("swsusp: resume file found\n"); + else pr_debug("swsusp: Error %d check for resume file\n", error); + return error; +} + +/** + * swsusp_read - Read saved image from swap. + */ + +int swsusp_read(void) +{ + int error; + + if (IS_ERR(resume_bdev)) { + pr_debug("swsusp: block device not initialised\n"); + return PTR_ERR(resume_bdev); + } + + error = read_suspend_image(); + blkdev_put(resume_bdev); + memset(key_iv, 0, MAXKEY+MAXIV); + if (!error) + pr_debug("swsusp: Reading resume file was successful\n"); + else + pr_debug("swsusp: Error %d resuming\n", error); return error; } diff --git a/trunk/kernel/sysctl.c b/trunk/kernel/sysctl.c index a85047bb5739..345f4a1d533f 100644 --- a/trunk/kernel/sysctl.c +++ b/trunk/kernel/sysctl.c @@ -108,7 +108,7 @@ extern int pwrsw_enabled; extern int unaligned_enabled; #endif -#ifdef CONFIG_S390 +#ifdef CONFIG_ARCH_S390 #ifdef CONFIG_MATHEMU extern int sysctl_ieee_emulation_warnings; #endif @@ -542,7 +542,7 @@ static ctl_table kern_table[] = { .extra1 = &minolduid, .extra2 = &maxolduid, }, -#ifdef CONFIG_S390 +#ifdef CONFIG_ARCH_S390 #ifdef CONFIG_MATHEMU { .ctl_name = KERN_IEEE_EMULATION_WARNINGS, @@ -644,7 +644,7 @@ static ctl_table kern_table[] = { .mode = 0644, .proc_handler = &proc_dointvec, }, -#if defined(CONFIG_S390) +#if defined(CONFIG_ARCH_S390) { .ctl_name = KERN_SPIN_RETRY, .procname = "spin_retry", diff --git a/trunk/lib/Kconfig.debug b/trunk/lib/Kconfig.debug index 80598cfd728c..156822e3cc79 100644 --- a/trunk/lib/Kconfig.debug +++ b/trunk/lib/Kconfig.debug @@ -32,7 +32,7 @@ config MAGIC_SYSRQ config LOG_BUF_SHIFT int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL range 12 21 - default 17 if S390 + default 17 if ARCH_S390 default 16 if X86_NUMAQ || IA64 default 15 if SMP default 14 @@ -172,8 +172,7 @@ config DEBUG_VM bool "Debug VM" depends on DEBUG_KERNEL help - Enable this to turn on extended checks in the virtual-memory system - that may impact performance. + Enable this to debug the virtual-memory system. If unsure, say N. diff --git a/trunk/lib/swiotlb.c b/trunk/lib/swiotlb.c index 3b482052f403..1ff8dcebf7c6 100644 --- a/trunk/lib/swiotlb.c +++ b/trunk/lib/swiotlb.c @@ -142,7 +142,8 @@ swiotlb_init_with_default_size (size_t default_size) /* * Get IO TLB memory from the low pages */ - io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT)); + io_tlb_start = alloc_bootmem_low_pages_limit(io_tlb_nslabs * + (1 << IO_TLB_SHIFT), 0x100000000); if (!io_tlb_start) panic("Cannot allocate SWIOTLB buffer"); io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT); diff --git a/trunk/mm/Kconfig b/trunk/mm/Kconfig index b3db11f137e0..21eb51d4da8f 100644 --- a/trunk/mm/Kconfig +++ b/trunk/mm/Kconfig @@ -11,7 +11,7 @@ choice config FLATMEM_MANUAL bool "Flat Memory" - depends on !(ARCH_DISCONTIGMEM_ENABLE || ARCH_SPARSEMEM_ENABLE) || ARCH_FLATMEM_ENABLE + depends on !ARCH_DISCONTIGMEM_ENABLE || ARCH_FLATMEM_ENABLE help This option allows you to change some of the ways that Linux manages its memory internally. Most users will diff --git a/trunk/mm/bootmem.c b/trunk/mm/bootmem.c index 35c32290f717..16b9465eb4eb 100644 --- a/trunk/mm/bootmem.c +++ b/trunk/mm/bootmem.c @@ -296,12 +296,20 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat) unsigned long v = ~map[i / BITS_PER_LONG]; if (gofast && v == ~0UL) { - int order; + int j, order; page = pfn_to_page(pfn); count += BITS_PER_LONG; + __ClearPageReserved(page); order = ffs(BITS_PER_LONG) - 1; - __free_pages_bootmem(page, order); + set_page_refs(page, order); + for (j = 1; j < BITS_PER_LONG; j++) { + if (j + 16 < BITS_PER_LONG) + prefetchw(page + j + 16); + __ClearPageReserved(page + j); + set_page_count(page + j, 0); + } + __free_pages(page, order); i += BITS_PER_LONG; page += BITS_PER_LONG; } else if (v) { @@ -311,7 +319,9 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat) for (m = 1; m && i < idx; m<<=1, page++, i++) { if (v & m) { count++; - __free_pages_bootmem(page, 0); + __ClearPageReserved(page); + set_page_refs(page, 0); + __free_page(page); } } } else { @@ -329,7 +339,9 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat) count = 0; for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) { count++; - __free_pages_bootmem(page, 0); + __ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); } total += count; bdata->node_bootmem_map = NULL; @@ -381,14 +393,15 @@ unsigned long __init free_all_bootmem (void) return(free_all_bootmem_core(NODE_DATA(0))); } -void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned long goal) +void * __init __alloc_bootmem_limit (unsigned long size, unsigned long align, unsigned long goal, + unsigned long limit) { pg_data_t *pgdat = pgdat_list; void *ptr; for_each_pgdat(pgdat) if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, - align, goal, 0))) + align, goal, limit))) return(ptr); /* @@ -400,40 +413,15 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align, unsigned } -void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, unsigned long align, - unsigned long goal) +void * __init __alloc_bootmem_node_limit (pg_data_t *pgdat, unsigned long size, unsigned long align, + unsigned long goal, unsigned long limit) { void *ptr; - ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, 0); + ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal, limit); if (ptr) return (ptr); - return __alloc_bootmem(size, align, goal); -} - -#define LOW32LIMIT 0xffffffff - -void * __init __alloc_bootmem_low(unsigned long size, unsigned long align, unsigned long goal) -{ - pg_data_t *pgdat = pgdat_list; - void *ptr; - - for_each_pgdat(pgdat) - if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, - align, goal, LOW32LIMIT))) - return(ptr); - - /* - * Whoops, we cannot satisfy the allocation request. - */ - printk(KERN_ALERT "low bootmem alloc of %lu bytes failed!\n", size); - panic("Out of low memory"); - return NULL; + return __alloc_bootmem_limit(size, align, goal, limit); } -void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size, - unsigned long align, unsigned long goal) -{ - return __alloc_bootmem_core(pgdat->bdata, size, align, goal, LOW32LIMIT); -} diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index 4ef24a397684..6e1d08a2b8b9 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -555,12 +555,11 @@ struct page *find_lock_page(struct address_space *mapping, page_cache_get(page); if (TestSetPageLocked(page)) { read_unlock_irq(&mapping->tree_lock); - __lock_page(page); + lock_page(page); read_lock_irq(&mapping->tree_lock); /* Has the page been truncated while we slept? */ - if (unlikely(page->mapping != mapping || - page->index != offset)) { + if (page->mapping != mapping || page->index != offset) { unlock_page(page); page_cache_release(page); goto repeat; diff --git a/trunk/mm/hugetlb.c b/trunk/mm/hugetlb.c index f4c43d7980ba..3e52df7c471b 100644 --- a/trunk/mm/hugetlb.c +++ b/trunk/mm/hugetlb.c @@ -11,8 +11,6 @@ #include #include #include -#include - #include #include @@ -38,21 +36,18 @@ static void enqueue_huge_page(struct page *page) free_huge_pages_node[nid]++; } -static struct page *dequeue_huge_page(struct vm_area_struct *vma, - unsigned long address) +static struct page *dequeue_huge_page(void) { int nid = numa_node_id(); struct page *page = NULL; - struct zonelist *zonelist = huge_zonelist(vma, address); - struct zone **z; - for (z = zonelist->zones; *z; z++) { - nid = (*z)->zone_pgdat->node_id; - if (!list_empty(&hugepage_freelists[nid])) - break; + if (list_empty(&hugepage_freelists[nid])) { + for (nid = 0; nid < MAX_NUMNODES; ++nid) + if (!list_empty(&hugepage_freelists[nid])) + break; } - - if (*z) { + if (nid >= 0 && nid < MAX_NUMNODES && + !list_empty(&hugepage_freelists[nid])) { page = list_entry(hugepage_freelists[nid].next, struct page, lru); list_del(&page->lru); @@ -90,13 +85,13 @@ void free_huge_page(struct page *page) spin_unlock(&hugetlb_lock); } -struct page *alloc_huge_page(struct vm_area_struct *vma, unsigned long addr) +struct page *alloc_huge_page(void) { struct page *page; int i; spin_lock(&hugetlb_lock); - page = dequeue_huge_page(vma, addr); + page = dequeue_huge_page(); if (!page) { spin_unlock(&hugetlb_lock); return NULL; @@ -199,7 +194,7 @@ static unsigned long set_max_huge_pages(unsigned long count) spin_lock(&hugetlb_lock); try_to_free_low(count); while (count < nr_huge_pages) { - struct page *page = dequeue_huge_page(NULL, 0); + struct page *page = dequeue_huge_page(); if (!page) break; update_and_free_page(page); @@ -266,12 +261,11 @@ struct vm_operations_struct hugetlb_vm_ops = { .nopage = hugetlb_nopage, }; -static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page, - int writable) +static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page) { pte_t entry; - if (writable) { + if (vma->vm_flags & VM_WRITE) { entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))); } else { @@ -283,27 +277,12 @@ static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page, return entry; } -static void set_huge_ptep_writable(struct vm_area_struct *vma, - unsigned long address, pte_t *ptep) -{ - pte_t entry; - - entry = pte_mkwrite(pte_mkdirty(*ptep)); - ptep_set_access_flags(vma, address, ptep, entry, 1); - update_mmu_cache(vma, address, entry); - lazy_mmu_prot_update(entry); -} - - int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { pte_t *src_pte, *dst_pte, entry; struct page *ptepage; unsigned long addr; - int cow; - - cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE; for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { src_pte = huge_pte_offset(src, addr); @@ -315,8 +294,6 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, spin_lock(&dst->page_table_lock); spin_lock(&src->page_table_lock); if (!pte_none(*src_pte)) { - if (cow) - ptep_set_wrprotect(src, addr, src_pte); entry = *src_pte; ptepage = pte_page(entry); get_page(ptepage); @@ -368,63 +345,57 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, flush_tlb_range(vma, start, end); } -static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, - unsigned long address, pte_t *ptep, pte_t pte) +static struct page *find_lock_huge_page(struct address_space *mapping, + unsigned long idx) { - struct page *old_page, *new_page; - int i, avoidcopy; - - old_page = pte_page(pte); - - /* If no-one else is actually using this page, avoid the copy - * and just make the page writable */ - avoidcopy = (page_count(old_page) == 1); - if (avoidcopy) { - set_huge_ptep_writable(vma, address, ptep); - return VM_FAULT_MINOR; - } + struct page *page; + int err; + struct inode *inode = mapping->host; + unsigned long size; - page_cache_get(old_page); - new_page = alloc_huge_page(vma, address); +retry: + page = find_lock_page(mapping, idx); + if (page) + goto out; - if (!new_page) { - page_cache_release(old_page); + /* Check to make sure the mapping hasn't been truncated */ + size = i_size_read(inode) >> HPAGE_SHIFT; + if (idx >= size) + goto out; - /* Logically this is OOM, not a SIGBUS, but an OOM - * could cause the kernel to go killing other - * processes which won't help the hugepage situation - * at all (?) */ - return VM_FAULT_SIGBUS; + if (hugetlb_get_quota(mapping)) + goto out; + page = alloc_huge_page(); + if (!page) { + hugetlb_put_quota(mapping); + goto out; } - spin_unlock(&mm->page_table_lock); - for (i = 0; i < HPAGE_SIZE/PAGE_SIZE; i++) - copy_user_highpage(new_page + i, old_page + i, - address + i*PAGE_SIZE); - spin_lock(&mm->page_table_lock); - - ptep = huge_pte_offset(mm, address & HPAGE_MASK); - if (likely(pte_same(*ptep, pte))) { - /* Break COW */ - set_huge_pte_at(mm, address, ptep, - make_huge_pte(vma, new_page, 1)); - /* Make the old page be freed below */ - new_page = old_page; + err = add_to_page_cache(page, mapping, idx, GFP_KERNEL); + if (err) { + put_page(page); + hugetlb_put_quota(mapping); + if (err == -EEXIST) + goto retry; + page = NULL; } - page_cache_release(new_page); - page_cache_release(old_page); - return VM_FAULT_MINOR; +out: + return page; } -int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, - unsigned long address, pte_t *ptep, int write_access) +int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long address, int write_access) { int ret = VM_FAULT_SIGBUS; unsigned long idx; unsigned long size; + pte_t *pte; struct page *page; struct address_space *mapping; - pte_t new_pte; + + pte = huge_pte_alloc(mm, address); + if (!pte) + goto out; mapping = vma->vm_file->f_mapping; idx = ((address - vma->vm_start) >> HPAGE_SHIFT) @@ -434,31 +405,9 @@ int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, * Use page lock to guard against racing truncation * before we get page_table_lock. */ -retry: - page = find_lock_page(mapping, idx); - if (!page) { - if (hugetlb_get_quota(mapping)) - goto out; - page = alloc_huge_page(vma, address); - if (!page) { - hugetlb_put_quota(mapping); - goto out; - } - - if (vma->vm_flags & VM_SHARED) { - int err; - - err = add_to_page_cache(page, mapping, idx, GFP_KERNEL); - if (err) { - put_page(page); - hugetlb_put_quota(mapping); - if (err == -EEXIST) - goto retry; - goto out; - } - } else - lock_page(page); - } + page = find_lock_huge_page(mapping, idx); + if (!page) + goto out; spin_lock(&mm->page_table_lock); size = i_size_read(mapping->host) >> HPAGE_SHIFT; @@ -466,19 +415,11 @@ int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, goto backout; ret = VM_FAULT_MINOR; - if (!pte_none(*ptep)) + if (!pte_none(*pte)) goto backout; add_mm_counter(mm, file_rss, HPAGE_SIZE / PAGE_SIZE); - new_pte = make_huge_pte(vma, page, ((vma->vm_flags & VM_WRITE) - && (vma->vm_flags & VM_SHARED))); - set_huge_pte_at(mm, address, ptep, new_pte); - - if (write_access && !(vma->vm_flags & VM_SHARED)) { - /* Optimization, do the COW without a second fault */ - ret = hugetlb_cow(mm, vma, address, ptep, new_pte); - } - + set_huge_pte_at(mm, address, pte, make_huge_pte(vma, page)); spin_unlock(&mm->page_table_lock); unlock_page(page); out: @@ -492,33 +433,6 @@ int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, goto out; } -int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, - unsigned long address, int write_access) -{ - pte_t *ptep; - pte_t entry; - int ret; - - ptep = huge_pte_alloc(mm, address); - if (!ptep) - return VM_FAULT_OOM; - - entry = *ptep; - if (pte_none(entry)) - return hugetlb_no_page(mm, vma, address, ptep, write_access); - - ret = VM_FAULT_MINOR; - - spin_lock(&mm->page_table_lock); - /* Check for a racing update before calling hugetlb_cow */ - if (likely(pte_same(entry, *ptep))) - if (write_access && !pte_write(entry)) - ret = hugetlb_cow(mm, vma, address, ptep, entry); - spin_unlock(&mm->page_table_lock); - - return ret; -} - int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, struct page **pages, struct vm_area_struct **vmas, unsigned long *position, int *length, int i) diff --git a/trunk/mm/internal.h b/trunk/mm/internal.h index 17256bb2f4ef..6bf134e8fb3d 100644 --- a/trunk/mm/internal.h +++ b/trunk/mm/internal.h @@ -9,22 +9,5 @@ * 2 of the License, or (at your option) any later version. */ -static inline void set_page_refs(struct page *page, int order) -{ -#ifdef CONFIG_MMU - set_page_count(page, 1); -#else - int i; - - /* - * We need to reference all the pages for this order, otherwise if - * anyone accesses one of the pages with (get/put) it will be freed. - * - eg: access_process_vm() - */ - for (i = 0; i < (1 << order); i++) - set_page_count(page + i, 1); -#endif /* CONFIG_MMU */ -} - -extern void fastcall __init __free_pages_bootmem(struct page *page, - unsigned int order); +/* page_alloc.c */ +extern void set_page_refs(struct page *page, int order); diff --git a/trunk/mm/madvise.c b/trunk/mm/madvise.c index ae0ae3ea299a..2b7cf0400a21 100644 --- a/trunk/mm/madvise.c +++ b/trunk/mm/madvise.c @@ -140,36 +140,6 @@ static long madvise_dontneed(struct vm_area_struct * vma, return 0; } -/* - * Application wants to free up the pages and associated backing store. - * This is effectively punching a hole into the middle of a file. - * - * NOTE: Currently, only shmfs/tmpfs is supported for this operation. - * Other filesystems return -ENOSYS. - */ -static long madvise_remove(struct vm_area_struct *vma, - unsigned long start, unsigned long end) -{ - struct address_space *mapping; - loff_t offset, endoff; - - if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB)) - return -EINVAL; - - if (!vma->vm_file || !vma->vm_file->f_mapping - || !vma->vm_file->f_mapping->host) { - return -EINVAL; - } - - mapping = vma->vm_file->f_mapping; - - offset = (loff_t)(start - vma->vm_start) - + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); - endoff = (loff_t)(end - vma->vm_start - 1) - + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); - return vmtruncate_range(mapping->host, offset, endoff); -} - static long madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, unsigned long start, unsigned long end, int behavior) @@ -182,9 +152,6 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, case MADV_RANDOM: error = madvise_behavior(vma, prev, start, end, behavior); break; - case MADV_REMOVE: - error = madvise_remove(vma, start, end); - break; case MADV_WILLNEED: error = madvise_willneed(vma, prev, start, end); @@ -223,8 +190,6 @@ madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, * some pages ahead. * MADV_DONTNEED - the application is finished with the given range, * so the kernel can free resources associated with it. - * MADV_REMOVE - the application wants to free up the given range of - * pages and associated backing store. * * return values: * zero - success diff --git a/trunk/mm/memory.c b/trunk/mm/memory.c index 7197f9bcd384..d8dde07a3656 100644 --- a/trunk/mm/memory.c +++ b/trunk/mm/memory.c @@ -1498,7 +1498,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, update_mmu_cache(vma, address, entry); lazy_mmu_prot_update(entry); lru_cache_add_active(new_page); - page_add_new_anon_rmap(new_page, vma, address); + page_add_anon_rmap(new_page, vma, address); /* Free the old page.. */ new_page = old_page; @@ -1770,31 +1770,8 @@ int vmtruncate(struct inode * inode, loff_t offset) out_busy: return -ETXTBSY; } -EXPORT_SYMBOL(vmtruncate); - -int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) -{ - struct address_space *mapping = inode->i_mapping; - /* - * If the underlying filesystem is not going to provide - * a way to truncate a range of blocks (punch a hole) - - * we should return failure right now. - */ - if (!inode->i_op || !inode->i_op->truncate_range) - return -ENOSYS; - - down(&inode->i_sem); - down_write(&inode->i_alloc_sem); - unmap_mapping_range(mapping, offset, (end - offset), 1); - truncate_inode_pages_range(mapping, offset, end); - inode->i_op->truncate_range(inode, offset, end); - up_write(&inode->i_alloc_sem); - up(&inode->i_sem); - - return 0; -} -EXPORT_SYMBOL(vmtruncate_range); +EXPORT_SYMBOL(vmtruncate); /* * Primitive swap readahead code. We simply read an aligned block of @@ -1977,7 +1954,8 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, goto release; inc_mm_counter(mm, anon_rss); lru_cache_add_active(page); - page_add_new_anon_rmap(page, vma, address); + SetPageReferenced(page); + page_add_anon_rmap(page, vma, address); } else { /* Map the ZERO_PAGE - vm_page_prot is readonly */ page = ZERO_PAGE(address); @@ -2108,7 +2086,7 @@ static int do_no_page(struct mm_struct *mm, struct vm_area_struct *vma, if (anon) { inc_mm_counter(mm, anon_rss); lru_cache_add_active(new_page); - page_add_new_anon_rmap(new_page, vma, address); + page_add_anon_rmap(new_page, vma, address); } else { inc_mm_counter(mm, file_rss); page_add_file_rmap(new_page); diff --git a/trunk/mm/memory_hotplug.c b/trunk/mm/memory_hotplug.c index a918f77f02f3..f6d4af8af8a8 100644 --- a/trunk/mm/memory_hotplug.c +++ b/trunk/mm/memory_hotplug.c @@ -42,6 +42,7 @@ extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn, int nr_pages); static int __add_section(struct zone *zone, unsigned long phys_start_pfn) { + struct pglist_data *pgdat = zone->zone_pgdat; int nr_pages = PAGES_PER_SECTION; int ret; diff --git a/trunk/mm/mempolicy.c b/trunk/mm/mempolicy.c index 0f1d2b8a952b..72f402cc9c9a 100644 --- a/trunk/mm/mempolicy.c +++ b/trunk/mm/mempolicy.c @@ -93,7 +93,7 @@ static kmem_cache_t *sn_cache; /* Highest zone. An specific allocation for a zone below that is not policied. */ -int policy_zone = ZONE_DMA; +static int policy_zone; struct mempolicy default_policy = { .refcnt = ATOMIC_INIT(1), /* never free it */ @@ -131,8 +131,17 @@ static struct zonelist *bind_zonelist(nodemask_t *nodes) if (!zl) return NULL; num = 0; - for_each_node_mask(nd, *nodes) - zl->zones[num++] = &NODE_DATA(nd)->node_zones[policy_zone]; + for_each_node_mask(nd, *nodes) { + int k; + for (k = MAX_NR_ZONES-1; k >= 0; k--) { + struct zone *z = &NODE_DATA(nd)->node_zones[k]; + if (!z->present_pages) + continue; + zl->zones[num++] = z; + if (k > policy_zone) + policy_zone = k; + } + } zl->zones[num] = NULL; return zl; } @@ -776,34 +785,6 @@ static unsigned offset_il_node(struct mempolicy *pol, return nid; } -/* Determine a node number for interleave */ -static inline unsigned interleave_nid(struct mempolicy *pol, - struct vm_area_struct *vma, unsigned long addr, int shift) -{ - if (vma) { - unsigned long off; - - off = vma->vm_pgoff; - off += (addr - vma->vm_start) >> shift; - return offset_il_node(pol, vma, off); - } else - return interleave_nodes(pol); -} - -/* Return a zonelist suitable for a huge page allocation. */ -struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr) -{ - struct mempolicy *pol = get_vma_policy(current, vma, addr); - - if (pol->policy == MPOL_INTERLEAVE) { - unsigned nid; - - nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT); - return NODE_DATA(nid)->node_zonelists + gfp_zone(GFP_HIGHUSER); - } - return zonelist_policy(GFP_HIGHUSER, pol); -} - /* Allocate a page in interleaved policy. Own path because it needs to do special accounting. */ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, @@ -852,8 +833,15 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) if (unlikely(pol->policy == MPOL_INTERLEAVE)) { unsigned nid; - - nid = interleave_nid(pol, vma, addr, PAGE_SHIFT); + if (vma) { + unsigned long off; + off = vma->vm_pgoff; + off += (addr - vma->vm_start) >> PAGE_SHIFT; + nid = offset_il_node(pol, vma, off); + } else { + /* fall back to process interleaving */ + nid = interleave_nodes(pol); + } return alloc_page_interleave(gfp, 0, nid); } return __alloc_pages(gfp, 0, zonelist_policy(gfp, pol)); @@ -951,6 +939,54 @@ void __mpol_free(struct mempolicy *p) kmem_cache_free(policy_cache, p); } +/* + * Hugetlb policy. Same as above, just works with node numbers instead of + * zonelists. + */ + +/* Find first node suitable for an allocation */ +int mpol_first_node(struct vm_area_struct *vma, unsigned long addr) +{ + struct mempolicy *pol = get_vma_policy(current, vma, addr); + + switch (pol->policy) { + case MPOL_DEFAULT: + return numa_node_id(); + case MPOL_BIND: + return pol->v.zonelist->zones[0]->zone_pgdat->node_id; + case MPOL_INTERLEAVE: + return interleave_nodes(pol); + case MPOL_PREFERRED: + return pol->v.preferred_node >= 0 ? + pol->v.preferred_node : numa_node_id(); + } + BUG(); + return 0; +} + +/* Find secondary valid nodes for an allocation */ +int mpol_node_valid(int nid, struct vm_area_struct *vma, unsigned long addr) +{ + struct mempolicy *pol = get_vma_policy(current, vma, addr); + + switch (pol->policy) { + case MPOL_PREFERRED: + case MPOL_DEFAULT: + case MPOL_INTERLEAVE: + return 1; + case MPOL_BIND: { + struct zone **z; + for (z = pol->v.zonelist->zones; *z; z++) + if ((*z)->zone_pgdat->node_id == nid) + return 1; + return 0; + } + default: + BUG(); + return 0; + } +} + /* * Shared memory backing store policy support. * diff --git a/trunk/mm/nommu.c b/trunk/mm/nommu.c index c10262d68232..c1196812876b 100644 --- a/trunk/mm/nommu.c +++ b/trunk/mm/nommu.c @@ -1177,10 +1177,3 @@ int in_gate_area_no_task(unsigned long addr) { return 0; } - -struct page *filemap_nopage(struct vm_area_struct *area, - unsigned long address, int *type) -{ - BUG(); - return NULL; -} diff --git a/trunk/mm/page-writeback.c b/trunk/mm/page-writeback.c index 5240e426c1f7..0166ea15c9ee 100644 --- a/trunk/mm/page-writeback.c +++ b/trunk/mm/page-writeback.c @@ -550,17 +550,11 @@ void __init page_writeback_init(void) int do_writepages(struct address_space *mapping, struct writeback_control *wbc) { - int ret; - if (wbc->nr_to_write <= 0) return 0; - wbc->for_writepages = 1; if (mapping->a_ops->writepages) - ret = mapping->a_ops->writepages(mapping, wbc); - else - ret = generic_writepages(mapping, wbc); - wbc->for_writepages = 0; - return ret; + return mapping->a_ops->writepages(mapping, wbc); + return generic_writepages(mapping, wbc); } /** diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index fd47494cb989..fe14a8c87fc2 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include "internal.h" @@ -54,8 +53,6 @@ unsigned long totalram_pages __read_mostly; unsigned long totalhigh_pages __read_mostly; long nr_swap_pages; -static void fastcall free_hot_cold_page(struct page *page, int cold); - /* * results with 256, 32 in the lowmem_reserve sysctl: * 1G machine -> (16M dma, 800M-16M normal, 1G-800M high) @@ -84,7 +81,6 @@ int min_free_kbytes = 1024; unsigned long __initdata nr_kernel_pages; unsigned long __initdata nr_all_pages; -#ifdef CONFIG_DEBUG_VM static int page_outside_zone_boundaries(struct zone *zone, struct page *page) { int ret = 0; @@ -126,23 +122,16 @@ static int bad_range(struct zone *zone, struct page *page) return 0; } -#else -static inline int bad_range(struct zone *zone, struct page *page) -{ - return 0; -} -#endif - -static void bad_page(struct page *page) +static void bad_page(const char *function, struct page *page) { - printk(KERN_EMERG "Bad page state in process '%s'\n" - "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n" - "Trying to fix it up, but a reboot is needed\n" - "Backtrace:\n", - current->comm, page, (int)(2*sizeof(unsigned long)), - (unsigned long)page->flags, page->mapping, - page_mapcount(page), page_count(page)); + printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n", + function, current->comm, page); + printk(KERN_EMERG "flags:0x%0*lx mapping:%p mapcount:%d count:%d\n", + (int)(2*sizeof(unsigned long)), (unsigned long)page->flags, + page->mapping, page_mapcount(page), page_count(page)); + printk(KERN_EMERG "Backtrace:\n"); dump_stack(); + printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n"); page->flags &= ~(1 << PG_lru | 1 << PG_private | 1 << PG_locked | @@ -195,15 +184,19 @@ static void destroy_compound_page(struct page *page, unsigned long order) int i; int nr_pages = 1 << order; - if (unlikely(page[1].index != order)) - bad_page(page); + if (!PageCompound(page)) + return; + + if (page[1].index != order) + bad_page(__FUNCTION__, page); for (i = 0; i < nr_pages; i++) { struct page *p = page + i; - if (unlikely(!PageCompound(p) | - (page_private(p) != (unsigned long)page))) - bad_page(page); + if (!PageCompound(p)) + bad_page(__FUNCTION__, page); + if (page_private(p) != (unsigned long)page) + bad_page(__FUNCTION__, page); ClearPageCompound(p); } } @@ -262,20 +255,14 @@ __find_combined_index(unsigned long page_idx, unsigned int order) /* * This function checks whether a page is free && is the buddy * we can do coalesce a page and its buddy if - * (a) the buddy is not in a hole && - * (b) the buddy is free && - * (c) the buddy is on the buddy system && - * (d) a page and its buddy have the same order. + * (a) the buddy is free && + * (b) the buddy is on the buddy system && + * (c) a page and its buddy have the same order. * for recording page's order, we use page_private(page) and PG_private. * */ static inline int page_is_buddy(struct page *page, int order) { -#ifdef CONFIG_HOLES_IN_ZONE - if (!pfn_valid(page_to_pfn(page))) - return 0; -#endif - if (PagePrivate(page) && (page_order(page) == order) && page_count(page) == 0) @@ -313,7 +300,7 @@ static inline void __free_pages_bulk (struct page *page, unsigned long page_idx; int order_size = 1 << order; - if (unlikely(PageCompound(page))) + if (unlikely(order)) destroy_compound_page(page, order); page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1); @@ -327,15 +314,17 @@ static inline void __free_pages_bulk (struct page *page, struct free_area *area; struct page *buddy; + combined_idx = __find_combined_index(page_idx, order); buddy = __page_find_buddy(page, page_idx, order); + + if (bad_range(zone, buddy)) + break; if (!page_is_buddy(buddy, order)) break; /* Move the buddy up one level. */ - list_del(&buddy->lru); area = zone->free_area + order; area->nr_free--; rmv_page_order(buddy); - combined_idx = __find_combined_index(page_idx, order); page = page + (combined_idx - page_idx); page_idx = combined_idx; order++; @@ -345,11 +334,11 @@ static inline void __free_pages_bulk (struct page *page, zone->free_area[order].nr_free++; } -static inline int free_pages_check(struct page *page) +static inline int free_pages_check(const char *function, struct page *page) { - if (unlikely(page_mapcount(page) | - (page->mapping != NULL) | - (page_count(page) != 0) | + if ( page_mapcount(page) || + page->mapping != NULL || + page_count(page) != 0 || (page->flags & ( 1 << PG_lru | 1 << PG_private | @@ -359,8 +348,8 @@ static inline int free_pages_check(struct page *page) 1 << PG_slab | 1 << PG_swapcache | 1 << PG_writeback | - 1 << PG_reserved )))) - bad_page(page); + 1 << PG_reserved ))) + bad_page(function, page); if (PageDirty(page)) __ClearPageDirty(page); /* @@ -386,10 +375,11 @@ static int free_pages_bulk(struct zone *zone, int count, struct list_head *list, unsigned int order) { + unsigned long flags; struct page *page = NULL; int ret = 0; - spin_lock(&zone->lock); + spin_lock_irqsave(&zone->lock, flags); zone->all_unreclaimable = 0; zone->pages_scanned = 0; while (!list_empty(list) && count--) { @@ -399,13 +389,12 @@ free_pages_bulk(struct zone *zone, int count, __free_pages_bulk(page, zone, order); ret++; } - spin_unlock(&zone->lock); + spin_unlock_irqrestore(&zone->lock, flags); return ret; } void __free_pages_ok(struct page *page, unsigned int order) { - unsigned long flags; LIST_HEAD(list); int i; int reserved = 0; @@ -419,49 +408,14 @@ void __free_pages_ok(struct page *page, unsigned int order) #endif for (i = 0 ; i < (1 << order) ; ++i) - reserved += free_pages_check(page + i); + reserved += free_pages_check(__FUNCTION__, page + i); if (reserved) return; list_add(&page->lru, &list); + mod_page_state(pgfree, 1 << order); kernel_map_pages(page, 1<lru, &list); - kernel_map_pages(page, 1 << order, 0); - free_pages_bulk(page_zone(page), 1, &list, order); - } } @@ -479,7 +433,8 @@ void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order) * * -- wli */ -static inline void expand(struct zone *zone, struct page *page, +static inline struct page * +expand(struct zone *zone, struct page *page, int low, int high, struct free_area *area) { unsigned long size = 1 << high; @@ -493,6 +448,24 @@ static inline void expand(struct zone *zone, struct page *page, area->nr_free++; set_page_order(&page[size], high); } + return page; +} + +void set_page_refs(struct page *page, int order) +{ +#ifdef CONFIG_MMU + set_page_count(page, 1); +#else + int i; + + /* + * We need to reference all the pages for this order, otherwise if + * anyone accesses one of the pages with (get/put) it will be freed. + * - eg: access_process_vm() + */ + for (i = 0; i < (1 << order); i++) + set_page_count(page + i, 1); +#endif /* CONFIG_MMU */ } /* @@ -500,9 +473,9 @@ static inline void expand(struct zone *zone, struct page *page, */ static int prep_new_page(struct page *page, int order) { - if (unlikely(page_mapcount(page) | - (page->mapping != NULL) | - (page_count(page) != 0) | + if ( page_mapcount(page) || + page->mapping != NULL || + page_count(page) != 0 || (page->flags & ( 1 << PG_lru | 1 << PG_private | @@ -513,8 +486,8 @@ static int prep_new_page(struct page *page, int order) 1 << PG_slab | 1 << PG_swapcache | 1 << PG_writeback | - 1 << PG_reserved )))) - bad_page(page); + 1 << PG_reserved ))) + bad_page(__FUNCTION__, page); /* * For now, we report if PG_reserved was found set, but do not @@ -552,8 +525,7 @@ static struct page *__rmqueue(struct zone *zone, unsigned int order) rmv_page_order(page); area->nr_free--; zone->free_pages -= 1UL << order; - expand(zone, page, order, current_order, area); - return page; + return expand(zone, page, order, current_order, area); } return NULL; @@ -567,17 +539,21 @@ static struct page *__rmqueue(struct zone *zone, unsigned int order) static int rmqueue_bulk(struct zone *zone, unsigned int order, unsigned long count, struct list_head *list) { + unsigned long flags; int i; + int allocated = 0; + struct page *page; - spin_lock(&zone->lock); + spin_lock_irqsave(&zone->lock, flags); for (i = 0; i < count; ++i) { - struct page *page = __rmqueue(zone, order); - if (unlikely(page == NULL)) + page = __rmqueue(zone, order); + if (page == NULL) break; + allocated++; list_add_tail(&page->lru, list); } - spin_unlock(&zone->lock); - return i; + spin_unlock_irqrestore(&zone->lock, flags); + return allocated; } #ifdef CONFIG_NUMA @@ -613,7 +589,6 @@ void drain_remote_pages(void) #if defined(CONFIG_PM) || defined(CONFIG_HOTPLUG_CPU) static void __drain_pages(unsigned int cpu) { - unsigned long flags; struct zone *zone; int i; @@ -625,10 +600,8 @@ static void __drain_pages(unsigned int cpu) struct per_cpu_pages *pcp; pcp = &pset->pcp[i]; - local_irq_save(flags); pcp->count -= free_pages_bulk(zone, pcp->count, &pcp->list, 0); - local_irq_restore(flags); } } } @@ -674,14 +647,18 @@ void drain_local_pages(void) } #endif /* CONFIG_PM */ -static void zone_statistics(struct zonelist *zonelist, struct zone *z, int cpu) +static void zone_statistics(struct zonelist *zonelist, struct zone *z) { #ifdef CONFIG_NUMA + unsigned long flags; + int cpu; pg_data_t *pg = z->zone_pgdat; pg_data_t *orig = zonelist->zones[0]->zone_pgdat; struct per_cpu_pageset *p; - p = zone_pcp(z, cpu); + local_irq_save(flags); + cpu = smp_processor_id(); + p = zone_pcp(z,cpu); if (pg == orig) { p->numa_hit++; } else { @@ -692,12 +669,14 @@ static void zone_statistics(struct zonelist *zonelist, struct zone *z, int cpu) p->local_node++; else p->other_node++; + local_irq_restore(flags); #endif } /* * Free a 0-order page */ +static void FASTCALL(free_hot_cold_page(struct page *page, int cold)); static void fastcall free_hot_cold_page(struct page *page, int cold) { struct zone *zone = page_zone(page); @@ -708,14 +687,14 @@ static void fastcall free_hot_cold_page(struct page *page, int cold) if (PageAnon(page)) page->mapping = NULL; - if (free_pages_check(page)) + if (free_pages_check(__FUNCTION__, page)) return; + inc_page_state(pgfree); kernel_map_pages(page, 1, 0); pcp = &zone_pcp(zone, get_cpu())->pcp[cold]; local_irq_save(flags); - __inc_page_state(pgfree); list_add(&page->lru, &pcp->list); pcp->count++; if (pcp->count >= pcp->high) @@ -748,58 +727,49 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags) * we cheat by calling it from here, in the order > 0 path. Saves a branch * or two. */ -static struct page *buffered_rmqueue(struct zonelist *zonelist, - struct zone *zone, int order, gfp_t gfp_flags) +static struct page * +buffered_rmqueue(struct zone *zone, int order, gfp_t gfp_flags) { unsigned long flags; struct page *page; int cold = !!(gfp_flags & __GFP_COLD); - int cpu; again: - cpu = get_cpu(); if (order == 0) { struct per_cpu_pages *pcp; - pcp = &zone_pcp(zone, cpu)->pcp[cold]; + page = NULL; + pcp = &zone_pcp(zone, get_cpu())->pcp[cold]; local_irq_save(flags); - if (!pcp->count) { + if (pcp->count <= pcp->low) pcp->count += rmqueue_bulk(zone, 0, pcp->batch, &pcp->list); - if (unlikely(!pcp->count)) - goto failed; + if (pcp->count) { + page = list_entry(pcp->list.next, struct page, lru); + list_del(&page->lru); + pcp->count--; } - page = list_entry(pcp->list.next, struct page, lru); - list_del(&page->lru); - pcp->count--; + local_irq_restore(flags); + put_cpu(); } else { spin_lock_irqsave(&zone->lock, flags); page = __rmqueue(zone, order); - spin_unlock(&zone->lock); - if (!page) - goto failed; + spin_unlock_irqrestore(&zone->lock, flags); } - __mod_page_state_zone(zone, pgalloc, 1 << order); - zone_statistics(zonelist, zone, cpu); - local_irq_restore(flags); - put_cpu(); - - BUG_ON(bad_range(zone, page)); - if (prep_new_page(page, order)) - goto again; + if (page != NULL) { + BUG_ON(bad_range(zone, page)); + mod_page_state_zone(zone, pgalloc, 1 << order); + if (prep_new_page(page, order)) + goto again; - if (gfp_flags & __GFP_ZERO) - prep_zero_page(page, order, gfp_flags); + if (gfp_flags & __GFP_ZERO) + prep_zero_page(page, order, gfp_flags); - if (order && (gfp_flags & __GFP_COMP)) - prep_compound_page(page, order); + if (order && (gfp_flags & __GFP_COMP)) + prep_compound_page(page, order); + } return page; - -failed: - local_irq_restore(flags); - put_cpu(); - return NULL; } #define ALLOC_NO_WATERMARKS 0x01 /* don't check watermarks at all */ @@ -875,8 +845,9 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, continue; } - page = buffered_rmqueue(zonelist, *z, order, gfp_mask); + page = buffered_rmqueue(*z, order, gfp_mask); if (page) { + zone_statistics(zonelist, *z); break; } } while (*(++z) != NULL); @@ -932,7 +903,8 @@ __alloc_pages(gfp_t gfp_mask, unsigned int order, alloc_flags |= ALLOC_HARDER; if (gfp_mask & __GFP_HIGH) alloc_flags |= ALLOC_HIGH; - alloc_flags |= ALLOC_CPUSET; + if (wait) + alloc_flags |= ALLOC_CPUSET; /* * Go through the zonelist again. Let __GFP_HIGH and allocations @@ -954,7 +926,7 @@ __alloc_pages(gfp_t gfp_mask, unsigned int order, nofail_alloc: /* go through the zonelist yet again, ignoring mins */ page = get_page_from_freelist(gfp_mask, order, - zonelist, ALLOC_NO_WATERMARKS); + zonelist, ALLOC_NO_WATERMARKS|ALLOC_CPUSET); if (page) goto got_pg; if (gfp_mask & __GFP_NOFAIL) { @@ -1199,11 +1171,12 @@ EXPORT_SYMBOL(nr_pagecache); DEFINE_PER_CPU(long, nr_pagecache_local) = 0; #endif -static void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask) +void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask) { int cpu = 0; memset(ret, 0, sizeof(*ret)); + cpus_and(*cpumask, *cpumask, cpu_online_map); cpu = first_cpu(*cpumask); while (cpu < NR_CPUS) { @@ -1251,12 +1224,12 @@ void get_full_page_state(struct page_state *ret) __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long), &mask); } -unsigned long read_page_state_offset(unsigned long offset) +unsigned long __read_page_state(unsigned long offset) { unsigned long ret = 0; int cpu; - for_each_cpu(cpu) { + for_each_online_cpu(cpu) { unsigned long in; in = (unsigned long)&per_cpu(page_states, cpu) + offset; @@ -1265,26 +1238,18 @@ unsigned long read_page_state_offset(unsigned long offset) return ret; } -void __mod_page_state_offset(unsigned long offset, unsigned long delta) -{ - void *ptr; - - ptr = &__get_cpu_var(page_states); - *(unsigned long *)(ptr + offset) += delta; -} -EXPORT_SYMBOL(__mod_page_state_offset); - -void mod_page_state_offset(unsigned long offset, unsigned long delta) +void __mod_page_state(unsigned long offset, unsigned long delta) { unsigned long flags; - void *ptr; + void* ptr; local_irq_save(flags); ptr = &__get_cpu_var(page_states); - *(unsigned long *)(ptr + offset) += delta; + *(unsigned long*)(ptr + offset) += delta; local_irq_restore(flags); } -EXPORT_SYMBOL(mod_page_state_offset); + +EXPORT_SYMBOL(__mod_page_state); void __get_zone_counts(unsigned long *active, unsigned long *inactive, unsigned long *free, struct pglist_data *pgdat) @@ -1370,7 +1335,7 @@ void show_free_areas(void) show_node(zone); printk("%s per-cpu:", zone->name); - if (!populated_zone(zone)) { + if (!zone->present_pages) { printk(" empty\n"); continue; } else @@ -1382,9 +1347,10 @@ void show_free_areas(void) pageset = zone_pcp(zone, cpu); for (temperature = 0; temperature < 2; temperature++) - printk("cpu %d %s: high %d, batch %d used:%d\n", + printk("cpu %d %s: low %d, high %d, batch %d used:%d\n", cpu, temperature ? "cold" : "hot", + pageset->pcp[temperature].low, pageset->pcp[temperature].high, pageset->pcp[temperature].batch, pageset->pcp[temperature].count); @@ -1447,7 +1413,7 @@ void show_free_areas(void) show_node(zone); printk("%s: ", zone->name); - if (!populated_zone(zone)) { + if (!zone->present_pages) { printk("empty\n"); continue; } @@ -1467,29 +1433,36 @@ void show_free_areas(void) /* * Builds allocation fallback zone lists. - * - * Add all populated zones of a node to the zonelist. */ -static int __init build_zonelists_node(pg_data_t *pgdat, - struct zonelist *zonelist, int nr_zones, int zone_type) -{ - struct zone *zone; - - BUG_ON(zone_type > ZONE_HIGHMEM); - - do { - zone = pgdat->node_zones + zone_type; - if (populated_zone(zone)) { +static int __init build_zonelists_node(pg_data_t *pgdat, struct zonelist *zonelist, int j, int k) +{ + switch (k) { + struct zone *zone; + default: + BUG(); + case ZONE_HIGHMEM: + zone = pgdat->node_zones + ZONE_HIGHMEM; + if (zone->present_pages) { #ifndef CONFIG_HIGHMEM - BUG_ON(zone_type > ZONE_NORMAL); + BUG(); #endif - zonelist->zones[nr_zones++] = zone; - check_highest_zone(zone_type); + zonelist->zones[j++] = zone; } - zone_type--; + case ZONE_NORMAL: + zone = pgdat->node_zones + ZONE_NORMAL; + if (zone->present_pages) + zonelist->zones[j++] = zone; + case ZONE_DMA32: + zone = pgdat->node_zones + ZONE_DMA32; + if (zone->present_pages) + zonelist->zones[j++] = zone; + case ZONE_DMA: + zone = pgdat->node_zones + ZONE_DMA; + if (zone->present_pages) + zonelist->zones[j++] = zone; + } - } while (zone_type >= 0); - return nr_zones; + return j; } static inline int highest_zone(int zone_bits) @@ -1736,6 +1709,8 @@ void __devinit memmap_init_zone(unsigned long size, int nid, unsigned long zone, for (pfn = start_pfn; pfn < end_pfn; pfn++, page++) { if (!early_pfn_valid(pfn)) continue; + if (!early_pfn_in_nid(pfn, nid)) + continue; page = pfn_to_page(pfn); set_page_links(page, zone, nid, pfn); set_page_count(page, 1); @@ -1819,12 +1794,14 @@ inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch) pcp = &p->pcp[0]; /* hot */ pcp->count = 0; + pcp->low = 0; pcp->high = 6 * batch; pcp->batch = max(1UL, 1 * batch); INIT_LIST_HEAD(&pcp->list); pcp = &p->pcp[1]; /* cold*/ pcp->count = 0; + pcp->low = 0; pcp->high = 2 * batch; pcp->batch = max(1UL, batch/2); INIT_LIST_HEAD(&pcp->list); @@ -2139,7 +2116,7 @@ static int frag_show(struct seq_file *m, void *arg) int order; for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) { - if (!populated_zone(zone)) + if (!zone->present_pages) continue; spin_lock_irqsave(&zone->lock, flags); @@ -2172,7 +2149,7 @@ static int zoneinfo_show(struct seq_file *m, void *arg) for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) { int i; - if (!populated_zone(zone)) + if (!zone->present_pages) continue; spin_lock_irqsave(&zone->lock, flags); @@ -2220,10 +2197,12 @@ static int zoneinfo_show(struct seq_file *m, void *arg) seq_printf(m, "\n cpu: %i pcp: %i" "\n count: %i" + "\n low: %i" "\n high: %i" "\n batch: %i", i, j, pageset->pcp[j].count, + pageset->pcp[j].low, pageset->pcp[j].high, pageset->pcp[j].batch); } @@ -2278,40 +2257,32 @@ static char *vmstat_text[] = { "pgpgout", "pswpin", "pswpout", - "pgalloc_high", + "pgalloc_normal", - "pgalloc_dma32", "pgalloc_dma", - "pgfree", "pgactivate", "pgdeactivate", "pgfault", "pgmajfault", - "pgrefill_high", "pgrefill_normal", - "pgrefill_dma32", "pgrefill_dma", "pgsteal_high", "pgsteal_normal", - "pgsteal_dma32", "pgsteal_dma", - "pgscan_kswapd_high", "pgscan_kswapd_normal", - "pgscan_kswapd_dma32", - "pgscan_kswapd_dma", + "pgscan_kswapd_dma", "pgscan_direct_high", "pgscan_direct_normal", - "pgscan_direct_dma32", "pgscan_direct_dma", - "pginodesteal", + "slabs_scanned", "kswapd_steal", "kswapd_inodesteal", diff --git a/trunk/mm/rmap.c b/trunk/mm/rmap.c index 6f3f7db27128..f853c6def159 100644 --- a/trunk/mm/rmap.c +++ b/trunk/mm/rmap.c @@ -434,30 +434,6 @@ int page_referenced(struct page *page, int is_locked) return referenced; } -/** - * page_set_anon_rmap - setup new anonymous rmap - * @page: the page to add the mapping to - * @vma: the vm area in which the mapping is added - * @address: the user virtual address mapped - */ -static void __page_set_anon_rmap(struct page *page, - struct vm_area_struct *vma, unsigned long address) -{ - struct anon_vma *anon_vma = vma->anon_vma; - - BUG_ON(!anon_vma); - anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; - page->mapping = (struct address_space *) anon_vma; - - page->index = linear_page_index(vma, address); - - /* - * nr_mapped state can be updated without turning off - * interrupts because it is not modified via interrupt. - */ - __inc_page_state(nr_mapped); -} - /** * page_add_anon_rmap - add pte mapping to an anonymous page * @page: the page to add the mapping to @@ -469,25 +445,18 @@ static void __page_set_anon_rmap(struct page *page, void page_add_anon_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address) { - if (atomic_inc_and_test(&page->_mapcount)) - __page_set_anon_rmap(page, vma, address); - /* else checking page index and mapping is racy */ -} + if (atomic_inc_and_test(&page->_mapcount)) { + struct anon_vma *anon_vma = vma->anon_vma; -/* - * page_add_new_anon_rmap - add pte mapping to a new anonymous page - * @page: the page to add the mapping to - * @vma: the vm area in which the mapping is added - * @address: the user virtual address mapped - * - * Same as page_add_anon_rmap but must only be called on *new* pages. - * This means the inc-and-test can be bypassed. - */ -void page_add_new_anon_rmap(struct page *page, - struct vm_area_struct *vma, unsigned long address) -{ - atomic_set(&page->_mapcount, 0); /* elevate count by 1 (starts at -1) */ - __page_set_anon_rmap(page, vma, address); + BUG_ON(!anon_vma); + anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; + page->mapping = (struct address_space *) anon_vma; + + page->index = linear_page_index(vma, address); + + inc_page_state(nr_mapped); + } + /* else checking page index and mapping is racy */ } /** @@ -502,7 +471,7 @@ void page_add_file_rmap(struct page *page) BUG_ON(!pfn_valid(page_to_pfn(page))); if (atomic_inc_and_test(&page->_mapcount)) - __inc_page_state(nr_mapped); + inc_page_state(nr_mapped); } /** @@ -526,7 +495,7 @@ void page_remove_rmap(struct page *page) */ if (page_test_and_clear_dirty(page)) set_page_dirty(page); - __dec_page_state(nr_mapped); + dec_page_state(nr_mapped); } } diff --git a/trunk/mm/shmem.c b/trunk/mm/shmem.c index a1f2f02af724..d9fc277940da 100644 --- a/trunk/mm/shmem.c +++ b/trunk/mm/shmem.c @@ -457,7 +457,7 @@ static void shmem_free_pages(struct list_head *next) } while (next); } -static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) +static void shmem_truncate(struct inode *inode) { struct shmem_inode_info *info = SHMEM_I(inode); unsigned long idx; @@ -475,27 +475,18 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) long nr_swaps_freed = 0; int offset; int freed; - int punch_hole = 0; inode->i_ctime = inode->i_mtime = CURRENT_TIME; - idx = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + idx = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; if (idx >= info->next_index) return; spin_lock(&info->lock); info->flags |= SHMEM_TRUNCATE; - if (likely(end == (loff_t) -1)) { - limit = info->next_index; - info->next_index = idx; - } else { - limit = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - if (limit > info->next_index) - limit = info->next_index; - punch_hole = 1; - } - + limit = info->next_index; + info->next_index = idx; topdir = info->i_indirect; - if (topdir && idx <= SHMEM_NR_DIRECT && !punch_hole) { + if (topdir && idx <= SHMEM_NR_DIRECT) { info->i_indirect = NULL; nr_pages_to_free++; list_add(&topdir->lru, &pages_to_free); @@ -582,12 +573,11 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) set_page_private(subdir, page_private(subdir) - freed); if (offset) spin_unlock(&info->lock); - if (!punch_hole) - BUG_ON(page_private(subdir) > offset); + BUG_ON(page_private(subdir) > offset); } if (offset) offset = 0; - else if (subdir && !page_private(subdir)) { + else if (subdir) { dir[diroff] = NULL; nr_pages_to_free++; list_add(&subdir->lru, &pages_to_free); @@ -604,7 +594,7 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) * Also, though shmem_getpage checks i_size before adding to * cache, no recheck after: so fix the narrow window there too. */ - truncate_inode_pages_range(inode->i_mapping, start, end); + truncate_inode_pages(inode->i_mapping, inode->i_size); } spin_lock(&info->lock); @@ -624,11 +614,6 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end) } } -static void shmem_truncate(struct inode *inode) -{ - shmem_truncate_range(inode, inode->i_size, (loff_t)-1); -} - static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; @@ -1270,7 +1255,7 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user) return retval; } -int shmem_mmap(struct file *file, struct vm_area_struct *vma) +static int shmem_mmap(struct file *file, struct vm_area_struct *vma) { file_accessed(file); vma->vm_ops = &shmem_vm_ops; @@ -2098,7 +2083,6 @@ static struct file_operations shmem_file_operations = { static struct inode_operations shmem_inode_operations = { .truncate = shmem_truncate, .setattr = shmem_notify_change, - .truncate_range = shmem_truncate_range, }; static struct inode_operations shmem_dir_inode_operations = { diff --git a/trunk/mm/swap.c b/trunk/mm/swap.c index ee6d71ccfa56..73d351439ef6 100644 --- a/trunk/mm/swap.c +++ b/trunk/mm/swap.c @@ -156,22 +156,16 @@ void fastcall lru_cache_add_active(struct page *page) put_cpu_var(lru_add_active_pvecs); } -static void __lru_add_drain(int cpu) +void lru_add_drain(void) { - struct pagevec *pvec = &per_cpu(lru_add_pvecs, cpu); + struct pagevec *pvec = &get_cpu_var(lru_add_pvecs); - /* CPU is dead, so no locking needed. */ if (pagevec_count(pvec)) __pagevec_lru_add(pvec); - pvec = &per_cpu(lru_add_active_pvecs, cpu); + pvec = &__get_cpu_var(lru_add_active_pvecs); if (pagevec_count(pvec)) __pagevec_lru_add_active(pvec); -} - -void lru_add_drain(void) -{ - __lru_add_drain(get_cpu()); - put_cpu(); + put_cpu_var(lru_add_pvecs); } /* @@ -418,6 +412,17 @@ void vm_acct_memory(long pages) } #ifdef CONFIG_HOTPLUG_CPU +static void lru_drain_cache(unsigned int cpu) +{ + struct pagevec *pvec = &per_cpu(lru_add_pvecs, cpu); + + /* CPU is dead, so no locking needed. */ + if (pagevec_count(pvec)) + __pagevec_lru_add(pvec); + pvec = &per_cpu(lru_add_active_pvecs, cpu); + if (pagevec_count(pvec)) + __pagevec_lru_add_active(pvec); +} /* Drop the CPU's cached committed space back into the central pool. */ static int cpu_swap_callback(struct notifier_block *nfb, @@ -430,7 +435,7 @@ static int cpu_swap_callback(struct notifier_block *nfb, if (action == CPU_DEAD) { atomic_add(*committed, &vm_committed_space); *committed = 0; - __lru_add_drain((long)hcpu); + lru_drain_cache((long)hcpu); } return NOTIFY_OK; } diff --git a/trunk/mm/swap_state.c b/trunk/mm/swap_state.c index fc2aecb70a95..0df9a57b1de8 100644 --- a/trunk/mm/swap_state.c +++ b/trunk/mm/swap_state.c @@ -14,7 +14,6 @@ #include #include #include -#include #include @@ -273,11 +272,12 @@ void free_page_and_swap_cache(struct page *page) */ void free_pages_and_swap_cache(struct page **pages, int nr) { + int chunk = 16; struct page **pagep = pages; lru_add_drain(); while (nr) { - int todo = min(nr, PAGEVEC_SIZE); + int todo = min(chunk, nr); int i; for (i = 0; i < todo; i++) diff --git a/trunk/mm/swapfile.c b/trunk/mm/swapfile.c index 6da4b28b896b..edafeace301f 100644 --- a/trunk/mm/swapfile.c +++ b/trunk/mm/swapfile.c @@ -211,26 +211,6 @@ swp_entry_t get_swap_page(void) return (swp_entry_t) {0}; } -swp_entry_t get_swap_page_of_type(int type) -{ - struct swap_info_struct *si; - pgoff_t offset; - - spin_lock(&swap_lock); - si = swap_info + type; - if (si->flags & SWP_WRITEOK) { - nr_swap_pages--; - offset = scan_swap_map(si); - if (offset) { - spin_unlock(&swap_lock); - return swp_entry(type, offset); - } - nr_swap_pages++; - } - spin_unlock(&swap_lock); - return (swp_entry_t) {0}; -} - static struct swap_info_struct * swap_info_get(swp_entry_t entry) { struct swap_info_struct * p; diff --git a/trunk/mm/tiny-shmem.c b/trunk/mm/tiny-shmem.c index cdc6d431972b..b58abcf44ed6 100644 --- a/trunk/mm/tiny-shmem.c +++ b/trunk/mm/tiny-shmem.c @@ -81,19 +81,13 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags) goto close_file; d_instantiate(dentry, inode); + inode->i_size = size; inode->i_nlink = 0; /* It is unlinked */ - file->f_vfsmnt = mntget(shm_mnt); file->f_dentry = dentry; file->f_mapping = inode->i_mapping; file->f_op = &ramfs_file_operations; file->f_mode = FMODE_WRITE | FMODE_READ; - - /* notify everyone as to the change of file size */ - error = do_truncate(dentry, size, file); - if (error < 0) - goto close_file; - return file; close_file: @@ -129,24 +123,3 @@ int shmem_unuse(swp_entry_t entry, struct page *page) { return 0; } - -int shmem_mmap(struct file *file, struct vm_area_struct *vma) -{ - file_accessed(file); -#ifndef CONFIG_MMU - return ramfs_nommu_mmap(file, vma); -#else - return 0; -#endif -} - -#ifndef CONFIG_MMU -unsigned long shmem_get_unmapped_area(struct file *file, - unsigned long addr, - unsigned long len, - unsigned long pgoff, - unsigned long flags) -{ - return ramfs_nommu_get_unmapped_area(file, addr, len, pgoff, flags); -} -#endif diff --git a/trunk/mm/truncate.c b/trunk/mm/truncate.c index 7dee32745901..9173ab500604 100644 --- a/trunk/mm/truncate.c +++ b/trunk/mm/truncate.c @@ -82,15 +82,12 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) } /** - * truncate_inode_pages - truncate range of pages specified by start and - * end byte offsets + * truncate_inode_pages - truncate *all* the pages from an offset * @mapping: mapping to truncate * @lstart: offset from which to truncate - * @lend: offset to which to truncate * - * Truncate the page cache, removing the pages that are between - * specified offsets (and zeroing out partial page - * (if lstart is not page aligned)). + * Truncate the page cache at a set offset, removing the pages that are beyond + * that offset (and zeroing out partial pages). * * Truncate takes two passes - the first pass is nonblocking. It will not * block on page locks and it will not block on writeback. The second pass @@ -104,12 +101,12 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) * We pass down the cache-hot hint to the page freeing code. Even if the * mapping is large, it is probably the case that the final pages are the most * recently touched, and freeing happens in ascending file offset order. + * + * Called under (and serialised by) inode->i_sem. */ -void truncate_inode_pages_range(struct address_space *mapping, - loff_t lstart, loff_t lend) +void truncate_inode_pages(struct address_space *mapping, loff_t lstart) { const pgoff_t start = (lstart + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT; - pgoff_t end; const unsigned partial = lstart & (PAGE_CACHE_SIZE - 1); struct pagevec pvec; pgoff_t next; @@ -118,22 +115,13 @@ void truncate_inode_pages_range(struct address_space *mapping, if (mapping->nrpages == 0) return; - BUG_ON((lend & (PAGE_CACHE_SIZE - 1)) != (PAGE_CACHE_SIZE - 1)); - end = (lend >> PAGE_CACHE_SHIFT); - pagevec_init(&pvec, 0); next = start; - while (next <= end && - pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { + while (pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) { for (i = 0; i < pagevec_count(&pvec); i++) { struct page *page = pvec.pages[i]; pgoff_t page_index = page->index; - if (page_index > end) { - next = page_index; - break; - } - if (page_index > next) next = page_index; next++; @@ -169,15 +157,9 @@ void truncate_inode_pages_range(struct address_space *mapping, next = start; continue; } - if (pvec.pages[0]->index > end) { - pagevec_release(&pvec); - break; - } for (i = 0; i < pagevec_count(&pvec); i++) { struct page *page = pvec.pages[i]; - if (page->index > end) - break; lock_page(page); wait_on_page_writeback(page); if (page->index > next) @@ -189,19 +171,7 @@ void truncate_inode_pages_range(struct address_space *mapping, pagevec_release(&pvec); } } -EXPORT_SYMBOL(truncate_inode_pages_range); -/** - * truncate_inode_pages - truncate *all* the pages from an offset - * @mapping: mapping to truncate - * @lstart: offset from which to truncate - * - * Called under (and serialised by) inode->i_sem. - */ -void truncate_inode_pages(struct address_space *mapping, loff_t lstart) -{ - truncate_inode_pages_range(mapping, lstart, (loff_t)-1); -} EXPORT_SYMBOL(truncate_inode_pages); /** diff --git a/trunk/mm/vmscan.c b/trunk/mm/vmscan.c index be8235fb1939..795a050fe471 100644 --- a/trunk/mm/vmscan.c +++ b/trunk/mm/vmscan.c @@ -63,6 +63,9 @@ struct scan_control { unsigned long nr_mapped; /* From page_state */ + /* How many pages shrink_cache() should reclaim */ + int nr_to_reclaim; + /* Ask shrink_caches, or shrink_zone to scan at this priority */ unsigned int priority; @@ -71,6 +74,9 @@ struct scan_control { int may_writepage; + /* Can pages be swapped as part of reclaim? */ + int may_swap; + /* This context's SWAP_CLUSTER_MAX. If freeing memory for * suspend, we effectively ignore SWAP_CLUSTER_MAX. * In this context, it doesn't matter that we scan the @@ -424,6 +430,8 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) * Try to allocate it some swap space here. */ if (PageAnon(page) && !PageSwapCache(page)) { + if (!sc->may_swap) + goto keep_locked; if (!add_to_swap(page)) goto activate_locked; } @@ -645,17 +653,17 @@ static void shrink_cache(struct zone *zone, struct scan_control *sc) goto done; max_scan -= nr_scan; + if (current_is_kswapd()) + mod_page_state_zone(zone, pgscan_kswapd, nr_scan); + else + mod_page_state_zone(zone, pgscan_direct, nr_scan); nr_freed = shrink_list(&page_list, sc); + if (current_is_kswapd()) + mod_page_state(kswapd_steal, nr_freed); + mod_page_state_zone(zone, pgsteal, nr_freed); + sc->nr_to_reclaim -= nr_freed; - local_irq_disable(); - if (current_is_kswapd()) { - __mod_page_state_zone(zone, pgscan_kswapd, nr_scan); - __mod_page_state(kswapd_steal, nr_freed); - } else - __mod_page_state_zone(zone, pgscan_direct, nr_scan); - __mod_page_state_zone(zone, pgsteal, nr_freed); - - spin_lock(&zone->lru_lock); + spin_lock_irq(&zone->lru_lock); /* * Put back any unfreeable pages. */ @@ -817,13 +825,11 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc) } } zone->nr_active += pgmoved; - spin_unlock(&zone->lru_lock); - - __mod_page_state_zone(zone, pgrefill, pgscanned); - __mod_page_state(pgdeactivate, pgdeactivate); - local_irq_enable(); - + spin_unlock_irq(&zone->lru_lock); pagevec_release(&pvec); + + mod_page_state_zone(zone, pgrefill, pgscanned); + mod_page_state(pgdeactivate, pgdeactivate); } /* @@ -855,6 +861,8 @@ shrink_zone(struct zone *zone, struct scan_control *sc) else nr_inactive = 0; + sc->nr_to_reclaim = sc->swap_cluster_max; + while (nr_active || nr_inactive) { if (nr_active) { sc->nr_to_scan = min(nr_active, @@ -868,6 +876,8 @@ shrink_zone(struct zone *zone, struct scan_control *sc) (unsigned long)sc->swap_cluster_max); nr_inactive -= sc->nr_to_scan; shrink_cache(zone, sc); + if (sc->nr_to_reclaim <= 0) + break; } } @@ -900,7 +910,7 @@ shrink_caches(struct zone **zones, struct scan_control *sc) for (i = 0; zones[i] != NULL; i++) { struct zone *zone = zones[i]; - if (!populated_zone(zone)) + if (zone->present_pages == 0) continue; if (!cpuset_zone_allowed(zone, __GFP_HARDWALL)) @@ -942,6 +952,7 @@ int try_to_free_pages(struct zone **zones, gfp_t gfp_mask) sc.gfp_mask = gfp_mask; sc.may_writepage = 0; + sc.may_swap = 1; inc_page_state(allocstall); @@ -1044,6 +1055,7 @@ static int balance_pgdat(pg_data_t *pgdat, int nr_pages, int order) total_reclaimed = 0; sc.gfp_mask = GFP_KERNEL; sc.may_writepage = 0; + sc.may_swap = 1; sc.nr_mapped = read_page_state(nr_mapped); inc_page_state(pageoutrun); @@ -1072,7 +1084,7 @@ static int balance_pgdat(pg_data_t *pgdat, int nr_pages, int order) for (i = pgdat->nr_zones - 1; i >= 0; i--) { struct zone *zone = pgdat->node_zones + i; - if (!populated_zone(zone)) + if (zone->present_pages == 0) continue; if (zone->all_unreclaimable && @@ -1109,7 +1121,7 @@ static int balance_pgdat(pg_data_t *pgdat, int nr_pages, int order) struct zone *zone = pgdat->node_zones + i; int nr_slab; - if (!populated_zone(zone)) + if (zone->present_pages == 0) continue; if (zone->all_unreclaimable && priority != DEF_PRIORITY) @@ -1261,7 +1273,7 @@ void wakeup_kswapd(struct zone *zone, int order) { pg_data_t *pgdat; - if (!populated_zone(zone)) + if (zone->present_pages == 0) return; pgdat = zone->zone_pgdat; @@ -1341,3 +1353,76 @@ static int __init kswapd_init(void) } module_init(kswapd_init) + + +/* + * Try to free up some pages from this zone through reclaim. + */ +int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) +{ + struct scan_control sc; + int nr_pages = 1 << order; + int total_reclaimed = 0; + + /* The reclaim may sleep, so don't do it if sleep isn't allowed */ + if (!(gfp_mask & __GFP_WAIT)) + return 0; + if (zone->all_unreclaimable) + return 0; + + sc.gfp_mask = gfp_mask; + sc.may_writepage = 0; + sc.may_swap = 0; + sc.nr_mapped = read_page_state(nr_mapped); + sc.nr_scanned = 0; + sc.nr_reclaimed = 0; + /* scan at the highest priority */ + sc.priority = 0; + disable_swap_token(); + + if (nr_pages > SWAP_CLUSTER_MAX) + sc.swap_cluster_max = nr_pages; + else + sc.swap_cluster_max = SWAP_CLUSTER_MAX; + + /* Don't reclaim the zone if there are other reclaimers active */ + if (atomic_read(&zone->reclaim_in_progress) > 0) + goto out; + + shrink_zone(zone, &sc); + total_reclaimed = sc.nr_reclaimed; + + out: + return total_reclaimed; +} + +asmlinkage long sys_set_zone_reclaim(unsigned int node, unsigned int zone, + unsigned int state) +{ + struct zone *z; + int i; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (node >= MAX_NUMNODES || !node_online(node)) + return -EINVAL; + + /* This will break if we ever add more zones */ + if (!(zone & (1<node_zones[i]; + + if (state) + z->reclaim_pages = 1; + else + z->reclaim_pages = 0; + } + + return 0; +} diff --git a/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c b/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c index 129e2bd36aff..5f1f806a0b11 100644 --- a/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -97,17 +97,13 @@ get_key(const void *p, const void *end, struct crypto_tfm **res) alg_mode = CRYPTO_TFM_MODE_CBC; break; default: - printk("gss_kerberos_mech: unsupported algorithm %d\n", alg); + dprintk("RPC: get_key: unsupported algorithm %d\n", alg); goto out_err_free_key; } - if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) { - printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name); + if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) goto out_err_free_key; - } - if (crypto_cipher_setkey(*res, key.data, key.len)) { - printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name); + if (crypto_cipher_setkey(*res, key.data, key.len)) goto out_err_free_tfm; - } kfree(key.data); return p; diff --git a/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c b/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c index 58400807d4df..39b3edc14694 100644 --- a/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c @@ -111,18 +111,14 @@ get_key(const void *p, const void *end, struct crypto_tfm **res, int *resalg) setkey = 0; break; default: - dprintk("gss_spkm3_mech: unsupported algorithm %d\n", *resalg); + dprintk("RPC: SPKM3 get_key: unsupported algorithm %d", *resalg); goto out_err_free_key; } - if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) { - printk("gss_spkm3_mech: unable to initialize crypto algorthm %s\n", alg_name); + if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) goto out_err_free_key; - } if (setkey) { - if (crypto_cipher_setkey(*res, key.data, key.len)) { - printk("gss_spkm3_mech: error setting key for crypto algorthm %s\n", alg_name); + if (crypto_cipher_setkey(*res, key.data, key.len)) goto out_err_free_tfm; - } } if(key.len > 0) diff --git a/trunk/net/sunrpc/auth_gss/gss_spkm3_seal.c b/trunk/net/sunrpc/auth_gss/gss_spkm3_seal.c index 86fbf7c3e39c..d1e12b25d6e2 100644 --- a/trunk/net/sunrpc/auth_gss/gss_spkm3_seal.c +++ b/trunk/net/sunrpc/auth_gss/gss_spkm3_seal.c @@ -59,7 +59,7 @@ spkm3_make_token(struct spkm3_ctx *ctx, char tokhdrbuf[25]; struct xdr_netobj md5cksum = {.len = 0, .data = NULL}; struct xdr_netobj mic_hdr = {.len = 0, .data = tokhdrbuf}; - int tokenlen = 0; + int tmsglen, tokenlen = 0; unsigned char *ptr; s32 now; int ctxelen = 0, ctxzbit = 0; @@ -92,23 +92,24 @@ spkm3_make_token(struct spkm3_ctx *ctx, } if (toktype == SPKM_MIC_TOK) { + tmsglen = 0; /* Calculate checksum over the mic-header */ asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit); spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data, ctxelen, ctxzbit); if (make_checksum(checksum_type, mic_hdr.data, mic_hdr.len, - text, 0, &md5cksum)) + text, &md5cksum)) goto out_err; asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit); - tokenlen = 10 + ctxelen + 1 + md5elen + 1; + tokenlen = 10 + ctxelen + 1 + 2 + md5elen + 1; /* Create token header using generic routines */ - token->len = g_token_size(&ctx->mech_used, tokenlen); + token->len = g_token_size(&ctx->mech_used, tokenlen + tmsglen); ptr = token->data; - g_make_token_header(&ctx->mech_used, tokenlen, &ptr); + g_make_token_header(&ctx->mech_used, tokenlen + tmsglen, &ptr); spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit); } else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */ diff --git a/trunk/net/sunrpc/auth_gss/gss_spkm3_token.c b/trunk/net/sunrpc/auth_gss/gss_spkm3_token.c index af0d7ce74686..1f824578d773 100644 --- a/trunk/net/sunrpc/auth_gss/gss_spkm3_token.c +++ b/trunk/net/sunrpc/auth_gss/gss_spkm3_token.c @@ -182,7 +182,6 @@ spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ct * *tokp points to the beginning of the SPKM_MIC token described * in rfc 2025, section 3.2.1: * - * toklen is the inner token length */ void spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hdr, struct xdr_netobj *md5cksum, int md5elen, int md5zbit) @@ -190,7 +189,7 @@ spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hd unsigned char *ict = *tokp; *(u8 *)ict++ = 0xa4; - *(u8 *)ict++ = toklen; + *(u8 *)ict++ = toklen - 2; memcpy(ict, mic_hdr->data, mic_hdr->len); ict += mic_hdr->len; diff --git a/trunk/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/trunk/net/sunrpc/auth_gss/gss_spkm3_unseal.c index 96851b0ba1ba..241d5b30dfcb 100644 --- a/trunk/net/sunrpc/auth_gss/gss_spkm3_unseal.c +++ b/trunk/net/sunrpc/auth_gss/gss_spkm3_unseal.c @@ -95,7 +95,7 @@ spkm3_read_token(struct spkm3_ctx *ctx, ret = GSS_S_DEFECTIVE_TOKEN; code = make_checksum(CKSUMTYPE_RSA_MD5, ptr + 2, mic_hdrlen + 2, - message_buffer, 0, &md5cksum); + message_buffer, &md5cksum); if (code) goto out; diff --git a/trunk/net/sunrpc/clnt.c b/trunk/net/sunrpc/clnt.c index 5530ac8c6df9..61c3abeaccae 100644 --- a/trunk/net/sunrpc/clnt.c +++ b/trunk/net/sunrpc/clnt.c @@ -374,23 +374,19 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, * Default callback for async RPC calls */ static void -rpc_default_callback(struct rpc_task *task, void *data) +rpc_default_callback(struct rpc_task *task) { } -static const struct rpc_call_ops rpc_default_ops = { - .rpc_call_done = rpc_default_callback, -}; - /* * Export the signal mask handling for synchronous code that * sleeps on RPC calls */ -#define RPC_INTR_SIGNALS (sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTERM)) +#define RPC_INTR_SIGNALS (sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGKILL)) static void rpc_save_sigmask(sigset_t *oldset, int intr) { - unsigned long sigallow = sigmask(SIGKILL); + unsigned long sigallow = 0; sigset_t sigmask; /* Block all signals except those listed in sigallow */ @@ -436,7 +432,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) BUG_ON(flags & RPC_TASK_ASYNC); status = -ENOMEM; - task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL); + task = rpc_new_task(clnt, NULL, flags); if (task == NULL) goto out; @@ -446,15 +442,14 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) rpc_call_setup(task, msg, 0); /* Set up the call info struct and execute the task */ - status = task->tk_status; - if (status == 0) { - atomic_inc(&task->tk_count); + if (task->tk_status == 0) { status = rpc_execute(task); - if (status == 0) - status = task->tk_status; + } else { + status = task->tk_status; + rpc_release_task(task); } + rpc_restore_sigmask(&oldset); - rpc_release_task(task); out: return status; } @@ -464,7 +459,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) */ int rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, - const struct rpc_call_ops *tk_ops, void *data) + rpc_action callback, void *data) { struct rpc_task *task; sigset_t oldset; @@ -477,9 +472,12 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, flags |= RPC_TASK_ASYNC; /* Create/initialize a new RPC task */ + if (!callback) + callback = rpc_default_callback; status = -ENOMEM; - if (!(task = rpc_new_task(clnt, flags, tk_ops, data))) + if (!(task = rpc_new_task(clnt, callback, flags))) goto out; + task->tk_calldata = data; /* Mask signals on GSS_AUTH upcalls */ rpc_task_sigmask(task, &oldset); @@ -513,7 +511,7 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) if (task->tk_status == 0) task->tk_action = call_start; else - task->tk_action = rpc_exit_task; + task->tk_action = NULL; } void @@ -538,18 +536,6 @@ size_t rpc_max_payload(struct rpc_clnt *clnt) } EXPORT_SYMBOL(rpc_max_payload); -/** - * rpc_force_rebind - force transport to check that remote port is unchanged - * @clnt: client to rebind - * - */ -void rpc_force_rebind(struct rpc_clnt *clnt) -{ - if (clnt->cl_autobind) - clnt->cl_port = 0; -} -EXPORT_SYMBOL(rpc_force_rebind); - /* * Restart an (async) RPC call. Usually called from within the * exit handler. @@ -656,26 +642,24 @@ call_reserveresult(struct rpc_task *task) /* * 2. Allocate the buffer. For details, see sched.c:rpc_malloc. - * (Note: buffer memory is freed in xprt_release). + * (Note: buffer memory is freed in rpc_task_release). */ static void call_allocate(struct rpc_task *task) { - struct rpc_rqst *req = task->tk_rqstp; - struct rpc_xprt *xprt = task->tk_xprt; unsigned int bufsiz; dprintk("RPC: %4d call_allocate (status %d)\n", task->tk_pid, task->tk_status); task->tk_action = call_bind; - if (req->rq_buffer) + if (task->tk_buffer) return; /* FIXME: compute buffer requirements more exactly using * auth->au_wslack */ bufsiz = task->tk_msg.rpc_proc->p_bufsiz + RPC_SLACK_SPACE; - if (xprt->ops->buf_alloc(task, bufsiz << 1) != NULL) + if (rpc_malloc(task, bufsiz << 1) != NULL) return; printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task); @@ -718,14 +702,14 @@ call_encode(struct rpc_task *task) task->tk_pid, task->tk_status); /* Default buffer setup */ - bufsiz = req->rq_bufsize >> 1; - sndbuf->head[0].iov_base = (void *)req->rq_buffer; + bufsiz = task->tk_bufsize >> 1; + sndbuf->head[0].iov_base = (void *)task->tk_buffer; sndbuf->head[0].iov_len = bufsiz; sndbuf->tail[0].iov_len = 0; sndbuf->page_len = 0; sndbuf->len = 0; sndbuf->buflen = bufsiz; - rcvbuf->head[0].iov_base = (void *)((char *)req->rq_buffer + bufsiz); + rcvbuf->head[0].iov_base = (void *)((char *)task->tk_buffer + bufsiz); rcvbuf->head[0].iov_len = bufsiz; rcvbuf->tail[0].iov_len = 0; rcvbuf->page_len = 0; @@ -865,7 +849,8 @@ call_connect_status(struct rpc_task *task) } /* Something failed: remote service port may have changed */ - rpc_force_rebind(clnt); + if (clnt->cl_autobind) + clnt->cl_port = 0; switch (status) { case -ENOTCONN: @@ -907,7 +892,7 @@ call_transmit(struct rpc_task *task) if (task->tk_status < 0) return; if (!task->tk_msg.rpc_proc->p_decode) { - task->tk_action = rpc_exit_task; + task->tk_action = NULL; rpc_wake_up_task(task); } return; @@ -946,7 +931,8 @@ call_status(struct rpc_task *task) break; case -ECONNREFUSED: case -ENOTCONN: - rpc_force_rebind(clnt); + if (clnt->cl_autobind) + clnt->cl_port = 0; task->tk_action = call_bind; break; case -EAGAIN: @@ -957,7 +943,8 @@ call_status(struct rpc_task *task) rpc_exit(task, status); break; default: - printk("%s: RPC call returned error %d\n", + if (clnt->cl_chatty) + printk("%s: RPC call returned error %d\n", clnt->cl_protname, -status); rpc_exit(task, status); break; @@ -992,18 +979,20 @@ call_timeout(struct rpc_task *task) dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid); if (RPC_IS_SOFT(task)) { - printk(KERN_NOTICE "%s: server %s not responding, timed out\n", + if (clnt->cl_chatty) + printk(KERN_NOTICE "%s: server %s not responding, timed out\n", clnt->cl_protname, clnt->cl_server); rpc_exit(task, -EIO); return; } - if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { + if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN)) { task->tk_flags |= RPC_CALL_MAJORSEEN; printk(KERN_NOTICE "%s: server %s not responding, still trying\n", clnt->cl_protname, clnt->cl_server); } - rpc_force_rebind(clnt); + if (clnt->cl_autobind) + clnt->cl_port = 0; retry: clnt->cl_stats->rpcretrans++; @@ -1025,7 +1014,7 @@ call_decode(struct rpc_task *task) dprintk("RPC: %4d call_decode (status %d)\n", task->tk_pid, task->tk_status); - if (task->tk_flags & RPC_CALL_MAJORSEEN) { + if (clnt->cl_chatty && (task->tk_flags & RPC_CALL_MAJORSEEN)) { printk(KERN_NOTICE "%s: server %s OK\n", clnt->cl_protname, clnt->cl_server); task->tk_flags &= ~RPC_CALL_MAJORSEEN; @@ -1050,14 +1039,13 @@ call_decode(struct rpc_task *task) sizeof(req->rq_rcv_buf)) != 0); /* Verify the RPC header */ - p = call_verify(task); - if (IS_ERR(p)) { - if (p == ERR_PTR(-EAGAIN)) - goto out_retry; - return; + if (!(p = call_verify(task))) { + if (task->tk_action == NULL) + return; + goto out_retry; } - task->tk_action = rpc_exit_task; + task->tk_action = NULL; if (decode) task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, @@ -1150,7 +1138,7 @@ call_verify(struct rpc_task *task) if ((n = ntohl(*p++)) != RPC_REPLY) { printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n); - goto out_garbage; + goto out_retry; } if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { if (--len < 0) @@ -1180,7 +1168,7 @@ call_verify(struct rpc_task *task) task->tk_pid); rpcauth_invalcred(task); task->tk_action = call_refresh; - goto out_retry; + return NULL; case RPC_AUTH_BADCRED: case RPC_AUTH_BADVERF: /* possibly garbled cred/verf? */ @@ -1190,7 +1178,7 @@ call_verify(struct rpc_task *task) dprintk("RPC: %4d call_verify: retry garbled creds\n", task->tk_pid); task->tk_action = call_bind; - goto out_retry; + return NULL; case RPC_AUTH_TOOWEAK: printk(KERN_NOTICE "call_verify: server requires stronger " "authentication.\n"); @@ -1205,7 +1193,7 @@ call_verify(struct rpc_task *task) } if (!(p = rpcauth_checkverf(task, p))) { printk(KERN_WARNING "call_verify: auth check failed\n"); - goto out_garbage; /* bad verifier, retry */ + goto out_retry; /* bad verifier, retry */ } len = p - (u32 *)iov->iov_base - 1; if (len < 0) @@ -1242,24 +1230,23 @@ call_verify(struct rpc_task *task) /* Also retry */ } -out_garbage: +out_retry: task->tk_client->cl_stats->rpcgarbage++; if (task->tk_garb_retry) { task->tk_garb_retry--; dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid); task->tk_action = call_bind; -out_retry: - return ERR_PTR(-EAGAIN); + return NULL; } printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__); out_eio: error = -EIO; out_err: rpc_exit(task, error); - return ERR_PTR(error); + return NULL; out_overflow: printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__); - goto out_garbage; + goto out_retry; } static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj) diff --git a/trunk/net/sunrpc/pmap_clnt.c b/trunk/net/sunrpc/pmap_clnt.c index 8139ce68e915..a398575f94b8 100644 --- a/trunk/net/sunrpc/pmap_clnt.c +++ b/trunk/net/sunrpc/pmap_clnt.c @@ -90,7 +90,8 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt) map->pm_binding = 0; rpc_wake_up(&map->pm_bindwait); spin_unlock(&pmap_lock); - rpc_exit(task, -EIO); + task->tk_status = -EIO; + task->tk_action = NULL; } #ifdef CONFIG_ROOT_NFS @@ -131,22 +132,21 @@ static void pmap_getport_done(struct rpc_task *task) { struct rpc_clnt *clnt = task->tk_client; - struct rpc_xprt *xprt = task->tk_xprt; struct rpc_portmap *map = clnt->cl_pmap; dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n", task->tk_pid, task->tk_status, clnt->cl_port); - - xprt->ops->set_port(xprt, 0); if (task->tk_status < 0) { /* Make the calling task exit with an error */ - task->tk_action = rpc_exit_task; + task->tk_action = NULL; } else if (clnt->cl_port == 0) { /* Program not registered */ - rpc_exit(task, -EACCES); + task->tk_status = -EACCES; + task->tk_action = NULL; } else { - xprt->ops->set_port(xprt, clnt->cl_port); + /* byte-swap port number first */ clnt->cl_port = htons(clnt->cl_port); + clnt->cl_xprt->addr.sin_port = clnt->cl_port; } spin_lock(&pmap_lock); map->pm_binding = 0; @@ -207,7 +207,7 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileg xprt = xprt_create_proto(proto, srvaddr, NULL); if (IS_ERR(xprt)) return (struct rpc_clnt *)xprt; - xprt->ops->set_port(xprt, RPC_PMAP_PORT); + xprt->addr.sin_port = htons(RPC_PMAP_PORT); if (!privileged) xprt->resvport = 0; @@ -217,6 +217,7 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileg RPC_AUTH_UNIX); if (!IS_ERR(clnt)) { clnt->cl_softrtry = 1; + clnt->cl_chatty = 1; clnt->cl_oneshot = 1; } return clnt; diff --git a/trunk/net/sunrpc/rpc_pipe.c b/trunk/net/sunrpc/rpc_pipe.c index 24cc23af9b95..16a2458f38f7 100644 --- a/trunk/net/sunrpc/rpc_pipe.c +++ b/trunk/net/sunrpc/rpc_pipe.c @@ -70,11 +70,8 @@ rpc_timeout_upcall_queue(void *data) struct inode *inode = &rpci->vfs_inode; down(&inode->i_sem); - if (rpci->ops == NULL) - goto out; if (rpci->nreaders == 0 && !list_empty(&rpci->pipe)) __rpc_purge_upcall(inode, -ETIMEDOUT); -out: up(&inode->i_sem); } @@ -116,6 +113,8 @@ rpc_close_pipes(struct inode *inode) { struct rpc_inode *rpci = RPC_I(inode); + cancel_delayed_work(&rpci->queue_timeout); + flush_scheduled_work(); down(&inode->i_sem); if (rpci->ops != NULL) { rpci->nreaders = 0; @@ -128,8 +127,6 @@ rpc_close_pipes(struct inode *inode) } rpc_inode_setowner(inode, NULL); up(&inode->i_sem); - cancel_delayed_work(&rpci->queue_timeout); - flush_scheduled_work(); } static struct inode * @@ -169,7 +166,7 @@ rpc_pipe_open(struct inode *inode, struct file *filp) static int rpc_pipe_release(struct inode *inode, struct file *filp) { - struct rpc_inode *rpci = RPC_I(inode); + struct rpc_inode *rpci = RPC_I(filp->f_dentry->d_inode); struct rpc_pipe_msg *msg; down(&inode->i_sem); diff --git a/trunk/net/sunrpc/sched.c b/trunk/net/sunrpc/sched.c index 7415406aa1ae..54e60a657500 100644 --- a/trunk/net/sunrpc/sched.c +++ b/trunk/net/sunrpc/sched.c @@ -41,6 +41,8 @@ static mempool_t *rpc_buffer_mempool __read_mostly; static void __rpc_default_timer(struct rpc_task *task); static void rpciod_killall(void); +static void rpc_free(struct rpc_task *task); + static void rpc_async_schedule(void *); /* @@ -262,35 +264,6 @@ void rpc_init_wait_queue(struct rpc_wait_queue *queue, const char *qname) } EXPORT_SYMBOL(rpc_init_wait_queue); -static int rpc_wait_bit_interruptible(void *word) -{ - if (signal_pending(current)) - return -ERESTARTSYS; - schedule(); - return 0; -} - -/* - * Mark an RPC call as having completed by clearing the 'active' bit - */ -static inline void rpc_mark_complete_task(struct rpc_task *task) -{ - rpc_clear_active(task); - wake_up_bit(&task->tk_runstate, RPC_TASK_ACTIVE); -} - -/* - * Allow callers to wait for completion of an RPC call - */ -int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) -{ - if (action == NULL) - action = rpc_wait_bit_interruptible; - return wait_on_bit(&task->tk_runstate, RPC_TASK_ACTIVE, - action, TASK_INTERRUPTIBLE); -} -EXPORT_SYMBOL(__rpc_wait_for_completion_task); - /* * Make an RPC task runnable. * @@ -326,7 +299,10 @@ static void rpc_make_runnable(struct rpc_task *task) static inline void rpc_schedule_run(struct rpc_task *task) { - rpc_set_active(task); + /* Don't run a child twice! */ + if (RPC_IS_ACTIVATED(task)) + return; + task->tk_active = 1; rpc_make_runnable(task); } @@ -348,7 +324,8 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, } /* Mark the task as being activated if so needed */ - rpc_set_active(task); + if (!RPC_IS_ACTIVATED(task)) + task->tk_active = 1; __rpc_add_wait_queue(q, task); @@ -578,29 +555,36 @@ __rpc_atrun(struct rpc_task *task) } /* - * Helper to call task->tk_ops->rpc_call_prepare + * Helper that calls task->tk_exit if it exists and then returns + * true if we should exit __rpc_execute. */ -static void rpc_prepare_task(struct rpc_task *task) +static inline int __rpc_do_exit(struct rpc_task *task) { - task->tk_ops->rpc_call_prepare(task, task->tk_calldata); -} - -/* - * Helper that calls task->tk_ops->rpc_call_done if it exists - */ -void rpc_exit_task(struct rpc_task *task) -{ - task->tk_action = NULL; - if (task->tk_ops->rpc_call_done != NULL) { - task->tk_ops->rpc_call_done(task, task->tk_calldata); + if (task->tk_exit != NULL) { + lock_kernel(); + task->tk_exit(task); + unlock_kernel(); + /* If tk_action is non-null, we should restart the call */ if (task->tk_action != NULL) { - WARN_ON(RPC_ASSASSINATED(task)); - /* Always release the RPC slot and buffer memory */ - xprt_release(task); + if (!RPC_ASSASSINATED(task)) { + /* Release RPC slot and buffer memory */ + xprt_release(task); + rpc_free(task); + return 0; + } + printk(KERN_ERR "RPC: dead task tried to walk away.\n"); } } + return 1; +} + +static int rpc_wait_bit_interruptible(void *word) +{ + if (signal_pending(current)) + return -ERESTARTSYS; + schedule(); + return 0; } -EXPORT_SYMBOL(rpc_exit_task); /* * This is the RPC `scheduler' (or rather, the finite state machine). @@ -647,11 +631,12 @@ static int __rpc_execute(struct rpc_task *task) * by someone else. */ if (!RPC_IS_QUEUED(task)) { - if (task->tk_action == NULL) + if (task->tk_action != NULL) { + lock_kernel(); + task->tk_action(task); + unlock_kernel(); + } else if (__rpc_do_exit(task)) break; - lock_kernel(); - task->tk_action(task); - unlock_kernel(); } /* @@ -691,9 +676,9 @@ static int __rpc_execute(struct rpc_task *task) dprintk("RPC: %4d sync task resuming\n", task->tk_pid); } - dprintk("RPC: %4d, return %d, status %d\n", task->tk_pid, status, task->tk_status); - /* Wake up anyone who is waiting for task completion */ - rpc_mark_complete_task(task); + dprintk("RPC: %4d exit() = %d\n", task->tk_pid, task->tk_status); + status = task->tk_status; + /* Release all resources associated with the task */ rpc_release_task(task); return status; @@ -711,7 +696,9 @@ static int __rpc_execute(struct rpc_task *task) int rpc_execute(struct rpc_task *task) { - rpc_set_active(task); + BUG_ON(task->tk_active); + + task->tk_active = 1; rpc_set_running(task); return __rpc_execute(task); } @@ -721,19 +708,17 @@ static void rpc_async_schedule(void *arg) __rpc_execute((struct rpc_task *)arg); } -/** - * rpc_malloc - allocate an RPC buffer - * @task: RPC task that will use this buffer - * @size: requested byte size +/* + * Allocate memory for RPC purposes. * * We try to ensure that some NFS reads and writes can always proceed * by using a mempool when allocating 'small' buffers. * In order to avoid memory starvation triggering more writebacks of * NFS requests, we use GFP_NOFS rather than GFP_KERNEL. */ -void * rpc_malloc(struct rpc_task *task, size_t size) +void * +rpc_malloc(struct rpc_task *task, size_t size) { - struct rpc_rqst *req = task->tk_rqstp; gfp_t gfp; if (task->tk_flags & RPC_TASK_SWAPPER) @@ -742,52 +727,42 @@ void * rpc_malloc(struct rpc_task *task, size_t size) gfp = GFP_NOFS; if (size > RPC_BUFFER_MAXSIZE) { - req->rq_buffer = kmalloc(size, gfp); - if (req->rq_buffer) - req->rq_bufsize = size; + task->tk_buffer = kmalloc(size, gfp); + if (task->tk_buffer) + task->tk_bufsize = size; } else { - req->rq_buffer = mempool_alloc(rpc_buffer_mempool, gfp); - if (req->rq_buffer) - req->rq_bufsize = RPC_BUFFER_MAXSIZE; + task->tk_buffer = mempool_alloc(rpc_buffer_mempool, gfp); + if (task->tk_buffer) + task->tk_bufsize = RPC_BUFFER_MAXSIZE; } - return req->rq_buffer; + return task->tk_buffer; } -/** - * rpc_free - free buffer allocated via rpc_malloc - * @task: RPC task with a buffer to be freed - * - */ -void rpc_free(struct rpc_task *task) +static void +rpc_free(struct rpc_task *task) { - struct rpc_rqst *req = task->tk_rqstp; - - if (req->rq_buffer) { - if (req->rq_bufsize == RPC_BUFFER_MAXSIZE) - mempool_free(req->rq_buffer, rpc_buffer_mempool); + if (task->tk_buffer) { + if (task->tk_bufsize == RPC_BUFFER_MAXSIZE) + mempool_free(task->tk_buffer, rpc_buffer_mempool); else - kfree(req->rq_buffer); - req->rq_buffer = NULL; - req->rq_bufsize = 0; + kfree(task->tk_buffer); + task->tk_buffer = NULL; + task->tk_bufsize = 0; } } /* * Creation and deletion of RPC task structures */ -void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) +void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action callback, int flags) { memset(task, 0, sizeof(*task)); init_timer(&task->tk_timer); task->tk_timer.data = (unsigned long) task; task->tk_timer.function = (void (*)(unsigned long)) rpc_run_timer; - atomic_set(&task->tk_count, 1); task->tk_client = clnt; task->tk_flags = flags; - task->tk_ops = tk_ops; - if (tk_ops->rpc_call_prepare != NULL) - task->tk_action = rpc_prepare_task; - task->tk_calldata = calldata; + task->tk_exit = callback; /* Initialize retry counters */ task->tk_garb_retry = 2; @@ -816,8 +791,6 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons list_add_tail(&task->tk_task, &all_tasks); spin_unlock(&rpc_sched_lock); - BUG_ON(task->tk_ops == NULL); - dprintk("RPC: %4d new task procpid %d\n", task->tk_pid, current->pid); } @@ -828,7 +801,8 @@ rpc_alloc_task(void) return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS); } -static void rpc_free_task(struct rpc_task *task) +static void +rpc_default_free_task(struct rpc_task *task) { dprintk("RPC: %4d freeing task\n", task->tk_pid); mempool_free(task, rpc_task_mempool); @@ -839,7 +813,8 @@ static void rpc_free_task(struct rpc_task *task) * clean up after an allocation failure, as the client may * have specified "oneshot". */ -struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *tk_ops, void *calldata) +struct rpc_task * +rpc_new_task(struct rpc_clnt *clnt, rpc_action callback, int flags) { struct rpc_task *task; @@ -847,7 +822,10 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc if (!task) goto cleanup; - rpc_init_task(task, clnt, flags, tk_ops, calldata); + rpc_init_task(task, clnt, callback, flags); + + /* Replace tk_release */ + task->tk_release = rpc_default_free_task; dprintk("RPC: %4d allocated task\n", task->tk_pid); task->tk_flags |= RPC_TASK_DYNAMIC; @@ -867,15 +845,11 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *clnt, int flags, const struct rpc void rpc_release_task(struct rpc_task *task) { - const struct rpc_call_ops *tk_ops = task->tk_ops; - void *calldata = task->tk_calldata; + dprintk("RPC: %4d release task\n", task->tk_pid); #ifdef RPC_DEBUG BUG_ON(task->tk_magic != RPC_TASK_MAGIC_ID); #endif - if (!atomic_dec_and_test(&task->tk_count)) - return; - dprintk("RPC: %4d release task\n", task->tk_pid); /* Remove from global task list */ spin_lock(&rpc_sched_lock); @@ -883,6 +857,7 @@ void rpc_release_task(struct rpc_task *task) spin_unlock(&rpc_sched_lock); BUG_ON (RPC_IS_QUEUED(task)); + task->tk_active = 0; /* Synchronously delete any running timer */ rpc_delete_timer(task); @@ -892,6 +867,7 @@ void rpc_release_task(struct rpc_task *task) xprt_release(task); if (task->tk_msg.rpc_cred) rpcauth_unbindcred(task); + rpc_free(task); if (task->tk_client) { rpc_release_client(task->tk_client); task->tk_client = NULL; @@ -900,33 +876,10 @@ void rpc_release_task(struct rpc_task *task) #ifdef RPC_DEBUG task->tk_magic = 0; #endif - if (task->tk_flags & RPC_TASK_DYNAMIC) - rpc_free_task(task); - if (tk_ops->rpc_release) - tk_ops->rpc_release(calldata); + if (task->tk_release) + task->tk_release(task); } -/** - * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it - * @clnt - pointer to RPC client - * @flags - RPC flags - * @ops - RPC call ops - * @data - user call data - */ -struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, - const struct rpc_call_ops *ops, - void *data) -{ - struct rpc_task *task; - task = rpc_new_task(clnt, flags, ops, data); - if (task == NULL) - return ERR_PTR(-ENOMEM); - atomic_inc(&task->tk_count); - rpc_execute(task); - return task; -} -EXPORT_SYMBOL(rpc_run_task); - /** * rpc_find_parent - find the parent of a child task. * @child: child task @@ -937,11 +890,12 @@ EXPORT_SYMBOL(rpc_run_task); * * Caller must hold childq.lock */ -static inline struct rpc_task *rpc_find_parent(struct rpc_task *child, struct rpc_task *parent) +static inline struct rpc_task *rpc_find_parent(struct rpc_task *child) { - struct rpc_task *task; + struct rpc_task *task, *parent; struct list_head *le; + parent = (struct rpc_task *) child->tk_calldata; task_for_each(task, le, &childq.tasks[0]) if (task == parent) return parent; @@ -949,22 +903,18 @@ static inline struct rpc_task *rpc_find_parent(struct rpc_task *child, struct rp return NULL; } -static void rpc_child_exit(struct rpc_task *child, void *calldata) +static void rpc_child_exit(struct rpc_task *child) { struct rpc_task *parent; spin_lock_bh(&childq.lock); - if ((parent = rpc_find_parent(child, calldata)) != NULL) { + if ((parent = rpc_find_parent(child)) != NULL) { parent->tk_status = child->tk_status; __rpc_wake_up_task(parent); } spin_unlock_bh(&childq.lock); } -static const struct rpc_call_ops rpc_child_ops = { - .rpc_call_done = rpc_child_exit, -}; - /* * Note: rpc_new_task releases the client after a failure. */ @@ -973,9 +923,11 @@ rpc_new_child(struct rpc_clnt *clnt, struct rpc_task *parent) { struct rpc_task *task; - task = rpc_new_task(clnt, RPC_TASK_ASYNC | RPC_TASK_CHILD, &rpc_child_ops, parent); + task = rpc_new_task(clnt, NULL, RPC_TASK_ASYNC | RPC_TASK_CHILD); if (!task) goto fail; + task->tk_exit = rpc_child_exit; + task->tk_calldata = parent; return task; fail: @@ -1111,7 +1063,7 @@ void rpc_show_tasks(void) return; } printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " - "-rpcwait -action- ---ops--\n"); + "-rpcwait -action- --exit--\n"); alltask_for_each(t, le, &all_tasks) { const char *rpc_waitq = "none"; @@ -1126,7 +1078,7 @@ void rpc_show_tasks(void) (t->tk_client ? t->tk_client->cl_prog : 0), t->tk_rqstp, t->tk_timeout, rpc_waitq, - t->tk_action, t->tk_ops); + t->tk_action, t->tk_exit); } spin_unlock(&rpc_sched_lock); } diff --git a/trunk/net/sunrpc/sunrpc_syms.c b/trunk/net/sunrpc/sunrpc_syms.c index 9f7373203592..a03d4b600c92 100644 --- a/trunk/net/sunrpc/sunrpc_syms.c +++ b/trunk/net/sunrpc/sunrpc_syms.c @@ -30,6 +30,8 @@ EXPORT_SYMBOL(rpc_init_task); EXPORT_SYMBOL(rpc_sleep_on); EXPORT_SYMBOL(rpc_wake_up_next); EXPORT_SYMBOL(rpc_wake_up_task); +EXPORT_SYMBOL(rpc_new_child); +EXPORT_SYMBOL(rpc_run_child); EXPORT_SYMBOL(rpciod_down); EXPORT_SYMBOL(rpciod_up); EXPORT_SYMBOL(rpc_new_task); @@ -43,6 +45,7 @@ EXPORT_SYMBOL(rpc_clone_client); EXPORT_SYMBOL(rpc_bind_new_program); EXPORT_SYMBOL(rpc_destroy_client); EXPORT_SYMBOL(rpc_shutdown_client); +EXPORT_SYMBOL(rpc_release_client); EXPORT_SYMBOL(rpc_killall_tasks); EXPORT_SYMBOL(rpc_call_sync); EXPORT_SYMBOL(rpc_call_async); @@ -117,6 +120,7 @@ EXPORT_SYMBOL(unix_domain_find); /* Generic XDR */ EXPORT_SYMBOL(xdr_encode_string); +EXPORT_SYMBOL(xdr_decode_string); EXPORT_SYMBOL(xdr_decode_string_inplace); EXPORT_SYMBOL(xdr_decode_netobj); EXPORT_SYMBOL(xdr_encode_netobj); diff --git a/trunk/net/sunrpc/svcauth_unix.c b/trunk/net/sunrpc/svcauth_unix.c index 3e6c694bbad1..cac2e774dd81 100644 --- a/trunk/net/sunrpc/svcauth_unix.c +++ b/trunk/net/sunrpc/svcauth_unix.c @@ -101,22 +101,10 @@ static void ip_map_put(struct cache_head *item, struct cache_detail *cd) } } -#if IP_HASHBITS == 8 -/* hash_long on a 64 bit machine is currently REALLY BAD for - * IP addresses in reverse-endian (i.e. on a little-endian machine). - * So use a trivial but reliable hash instead - */ -static inline int hash_ip(unsigned long ip) -{ - int hash = ip ^ (ip>>16); - return (hash ^ (hash>>8)) & 0xff; -} -#endif - static inline int ip_map_hash(struct ip_map *item) { return hash_str(item->m_class, IP_HASHBITS) ^ - hash_ip((unsigned long)item->m_addr.s_addr); + hash_long((unsigned long)item->m_addr.s_addr, IP_HASHBITS); } static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp) { diff --git a/trunk/net/sunrpc/svcsock.c b/trunk/net/sunrpc/svcsock.c index e67613e4eb18..d68eba481291 100644 --- a/trunk/net/sunrpc/svcsock.c +++ b/trunk/net/sunrpc/svcsock.c @@ -1026,7 +1026,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) } else { printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", svsk->sk_server->sv_name, -len); - goto err_delete; + svc_sock_received(svsk); } return len; diff --git a/trunk/net/sunrpc/xdr.c b/trunk/net/sunrpc/xdr.c index ca4bfa57e116..aaf08cdd19f0 100644 --- a/trunk/net/sunrpc/xdr.c +++ b/trunk/net/sunrpc/xdr.c @@ -92,6 +92,27 @@ xdr_encode_string(u32 *p, const char *string) return xdr_encode_array(p, string, strlen(string)); } +u32 * +xdr_decode_string(u32 *p, char **sp, int *lenp, int maxlen) +{ + unsigned int len; + char *string; + + if ((len = ntohl(*p++)) > maxlen) + return NULL; + if (lenp) + *lenp = len; + if ((len % 4) != 0) { + string = (char *) p; + } else { + string = (char *) (p - 1); + memmove(string, p, len); + } + string[len] = '\0'; + *sp = string; + return p + XDR_QUADLEN(len); +} + u32 * xdr_decode_string_inplace(u32 *p, char **sp, int *lenp, int maxlen) { diff --git a/trunk/net/sunrpc/xprt.c b/trunk/net/sunrpc/xprt.c index 8ff2c8acb223..6dda3860351f 100644 --- a/trunk/net/sunrpc/xprt.c +++ b/trunk/net/sunrpc/xprt.c @@ -119,17 +119,6 @@ int xprt_reserve_xprt(struct rpc_task *task) return 0; } -static void xprt_clear_locked(struct rpc_xprt *xprt) -{ - xprt->snd_task = NULL; - if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state) || xprt->shutdown) { - smp_mb__before_clear_bit(); - clear_bit(XPRT_LOCKED, &xprt->state); - smp_mb__after_clear_bit(); - } else - schedule_work(&xprt->task_cleanup); -} - /* * xprt_reserve_xprt_cong - serialize write access to transports * @task: task that is requesting access to the transport @@ -156,7 +145,9 @@ int xprt_reserve_xprt_cong(struct rpc_task *task) } return 1; } - xprt_clear_locked(xprt); + smp_mb__before_clear_bit(); + clear_bit(XPRT_LOCKED, &xprt->state); + smp_mb__after_clear_bit(); out_sleep: dprintk("RPC: %4d failed to lock transport %p\n", task->tk_pid, xprt); task->tk_timeout = 0; @@ -202,7 +193,9 @@ static void __xprt_lock_write_next(struct rpc_xprt *xprt) return; out_unlock: - xprt_clear_locked(xprt); + smp_mb__before_clear_bit(); + clear_bit(XPRT_LOCKED, &xprt->state); + smp_mb__after_clear_bit(); } static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) @@ -229,7 +222,9 @@ static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) return; } out_unlock: - xprt_clear_locked(xprt); + smp_mb__before_clear_bit(); + clear_bit(XPRT_LOCKED, &xprt->state); + smp_mb__after_clear_bit(); } /** @@ -242,7 +237,10 @@ static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) { if (xprt->snd_task == task) { - xprt_clear_locked(xprt); + xprt->snd_task = NULL; + smp_mb__before_clear_bit(); + clear_bit(XPRT_LOCKED, &xprt->state); + smp_mb__after_clear_bit(); __xprt_lock_write_next(xprt); } } @@ -258,7 +256,10 @@ void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task) { if (xprt->snd_task == task) { - xprt_clear_locked(xprt); + xprt->snd_task = NULL; + smp_mb__before_clear_bit(); + clear_bit(XPRT_LOCKED, &xprt->state); + smp_mb__after_clear_bit(); __xprt_lock_write_next_cong(xprt); } } @@ -534,6 +535,10 @@ void xprt_connect(struct rpc_task *task) dprintk("RPC: %4d xprt_connect xprt %p %s connected\n", task->tk_pid, xprt, (xprt_connected(xprt) ? "is" : "is not")); + if (xprt->shutdown) { + task->tk_status = -EIO; + return; + } if (!xprt->addr.sin_port) { task->tk_status = -EIO; return; @@ -682,6 +687,9 @@ int xprt_prepare_transmit(struct rpc_task *task) dprintk("RPC: %4d xprt_prepare_transmit\n", task->tk_pid); + if (xprt->shutdown) + return -EIO; + spin_lock_bh(&xprt->transport_lock); if (req->rq_received && !req->rq_bytes_sent) { err = req->rq_received; @@ -806,9 +814,11 @@ void xprt_reserve(struct rpc_task *task) struct rpc_xprt *xprt = task->tk_xprt; task->tk_status = -EIO; - spin_lock(&xprt->reserve_lock); - do_xprt_reserve(task); - spin_unlock(&xprt->reserve_lock); + if (!xprt->shutdown) { + spin_lock(&xprt->reserve_lock); + do_xprt_reserve(task); + spin_unlock(&xprt->reserve_lock); + } } static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt) @@ -828,8 +838,6 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) req->rq_timeout = xprt->timeout.to_initval; req->rq_task = task; req->rq_xprt = xprt; - req->rq_buffer = NULL; - req->rq_bufsize = 0; req->rq_xid = xprt_alloc_xid(xprt); req->rq_release_snd_buf = NULL; dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid, @@ -855,11 +863,10 @@ void xprt_release(struct rpc_task *task) if (!list_empty(&req->rq_list)) list_del(&req->rq_list); xprt->last_used = jiffies; - if (list_empty(&xprt->recv)) + if (list_empty(&xprt->recv) && !xprt->shutdown) mod_timer(&xprt->timer, xprt->last_used + xprt->idle_timeout); spin_unlock_bh(&xprt->transport_lock); - xprt->ops->buf_free(task); task->tk_rqstp = NULL; if (req->rq_release_snd_buf) req->rq_release_snd_buf(req); @@ -967,6 +974,16 @@ struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rp return xprt; } +static void xprt_shutdown(struct rpc_xprt *xprt) +{ + xprt->shutdown = 1; + rpc_wake_up(&xprt->sending); + rpc_wake_up(&xprt->resend); + xprt_wake_pending_tasks(xprt, -EIO); + rpc_wake_up(&xprt->backlog); + del_timer_sync(&xprt->timer); +} + /** * xprt_destroy - destroy an RPC transport, killing off all requests. * @xprt: transport to destroy @@ -975,8 +992,7 @@ struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rp int xprt_destroy(struct rpc_xprt *xprt) { dprintk("RPC: destroying transport %p\n", xprt); - xprt->shutdown = 1; - del_timer_sync(&xprt->timer); + xprt_shutdown(xprt); xprt->ops->destroy(xprt); kfree(xprt); diff --git a/trunk/net/sunrpc/xprtsock.c b/trunk/net/sunrpc/xprtsock.c index c458f8d1d6d1..77e8800d4127 100644 --- a/trunk/net/sunrpc/xprtsock.c +++ b/trunk/net/sunrpc/xprtsock.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -425,7 +424,7 @@ static void xs_close(struct rpc_xprt *xprt) struct sock *sk = xprt->inet; if (!sk) - goto clear_close_wait; + return; dprintk("RPC: xs_close xprt %p\n", xprt); @@ -442,10 +441,6 @@ static void xs_close(struct rpc_xprt *xprt) sk->sk_no_check = 0; sock_release(sock); -clear_close_wait: - smp_mb__before_clear_bit(); - clear_bit(XPRT_CLOSE_WAIT, &xprt->state); - smp_mb__after_clear_bit(); } /** @@ -805,13 +800,9 @@ static void xs_tcp_state_change(struct sock *sk) case TCP_SYN_SENT: case TCP_SYN_RECV: break; - case TCP_CLOSE_WAIT: - /* Try to schedule an autoclose RPC calls */ - set_bit(XPRT_CLOSE_WAIT, &xprt->state); - if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) - schedule_work(&xprt->task_cleanup); default: xprt_disconnect(xprt); + break; } out: read_unlock(&sk->sk_callback_lock); @@ -929,18 +920,6 @@ static void xs_udp_timer(struct rpc_task *task) xprt_adjust_cwnd(task, -ETIMEDOUT); } -/** - * xs_set_port - reset the port number in the remote endpoint address - * @xprt: generic transport - * @port: new port number - * - */ -static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) -{ - dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); - xprt->addr.sin_port = htons(port); -} - static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) { struct sockaddr_in myaddr = { @@ -1181,10 +1160,7 @@ static struct rpc_xprt_ops xs_udp_ops = { .set_buffer_size = xs_udp_set_buffer_size, .reserve_xprt = xprt_reserve_xprt_cong, .release_xprt = xprt_release_xprt_cong, - .set_port = xs_set_port, .connect = xs_connect, - .buf_alloc = rpc_malloc, - .buf_free = rpc_free, .send_request = xs_udp_send_request, .set_retrans_timeout = xprt_set_retrans_timeout_rtt, .timer = xs_udp_timer, @@ -1196,10 +1172,7 @@ static struct rpc_xprt_ops xs_udp_ops = { static struct rpc_xprt_ops xs_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xprt_release_xprt, - .set_port = xs_set_port, .connect = xs_connect, - .buf_alloc = rpc_malloc, - .buf_free = rpc_free, .send_request = xs_tcp_send_request, .set_retrans_timeout = xprt_set_retrans_timeout_def, .close = xs_close, diff --git a/trunk/security/keys/internal.h b/trunk/security/keys/internal.h index 39cba97c5eb9..db99ed434f3a 100644 --- a/trunk/security/keys/internal.h +++ b/trunk/security/keys/internal.h @@ -25,6 +25,7 @@ #define kdebug(FMT, a...) do {} while(0) #endif +extern struct key_type key_type_dead; extern struct key_type key_type_user; /*****************************************************************************/ diff --git a/trunk/security/keys/key.c b/trunk/security/keys/key.c index 99781b798312..01bcfecb7eae 100644 --- a/trunk/security/keys/key.c +++ b/trunk/security/keys/key.c @@ -36,7 +36,7 @@ static DECLARE_WORK(key_cleanup_task, key_cleanup, NULL); DECLARE_RWSEM(key_construction_sem); /* any key who's type gets unegistered will be re-typed to this */ -static struct key_type key_type_dead = { +struct key_type key_type_dead = { .name = "dead", }; @@ -240,9 +240,9 @@ static inline void key_alloc_serial(struct key *key) /* * allocate a key of the specified type * - update the user's quota to reflect the existence of the key - * - called from a key-type operation with key_types_sem read-locked by - * key_create_or_update() - * - this prevents unregistration of the key type + * - called from a key-type operation with key_types_sem read-locked by either + * key_create_or_update() or by key_duplicate(); this prevents unregistration + * of the key type * - upon return the key is as yet uninstantiated; the caller needs to either * instantiate the key or discard it before returning */ @@ -887,6 +887,56 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) EXPORT_SYMBOL(key_update); +/*****************************************************************************/ +/* + * duplicate a key, potentially with a revised description + * - must be supported by the keytype (keyrings for instance can be duplicated) + */ +struct key *key_duplicate(struct key *source, const char *desc) +{ + struct key *key; + int ret; + + key_check(source); + + if (!desc) + desc = source->description; + + down_read(&key_types_sem); + + ret = -EINVAL; + if (!source->type->duplicate) + goto error; + + /* allocate and instantiate a key */ + key = key_alloc(source->type, desc, current->fsuid, current->fsgid, + source->perm, 0); + if (IS_ERR(key)) + goto error_k; + + down_read(&source->sem); + ret = key->type->duplicate(key, source); + up_read(&source->sem); + if (ret < 0) + goto error2; + + atomic_inc(&key->user->nikeys); + set_bit(KEY_FLAG_INSTANTIATED, &key->flags); + + error_k: + up_read(&key_types_sem); + out: + return key; + + error2: + key_put(key); + error: + up_read(&key_types_sem); + key = ERR_PTR(ret); + goto out; + +} /* end key_duplicate() */ + /*****************************************************************************/ /* * revoke a key diff --git a/trunk/security/keys/keyring.c b/trunk/security/keys/keyring.c index 5d22c0388b32..4e9fa8be44b8 100644 --- a/trunk/security/keys/keyring.c +++ b/trunk/security/keys/keyring.c @@ -48,6 +48,7 @@ static inline unsigned keyring_hash(const char *desc) */ static int keyring_instantiate(struct key *keyring, const void *data, size_t datalen); +static int keyring_duplicate(struct key *keyring, const struct key *source); static int keyring_match(const struct key *keyring, const void *criterion); static void keyring_destroy(struct key *keyring); static void keyring_describe(const struct key *keyring, struct seq_file *m); @@ -58,6 +59,7 @@ struct key_type key_type_keyring = { .name = "keyring", .def_datalen = sizeof(struct keyring_list), .instantiate = keyring_instantiate, + .duplicate = keyring_duplicate, .match = keyring_match, .destroy = keyring_destroy, .describe = keyring_describe, @@ -68,7 +70,7 @@ struct key_type key_type_keyring = { * semaphore to serialise link/link calls to prevent two link calls in parallel * introducing a cycle */ -static DECLARE_RWSEM(keyring_serialise_link_sem); +DECLARE_RWSEM(keyring_serialise_link_sem); /*****************************************************************************/ /* @@ -116,6 +118,68 @@ static int keyring_instantiate(struct key *keyring, } /* end keyring_instantiate() */ +/*****************************************************************************/ +/* + * duplicate the list of subscribed keys from a source keyring into this one + */ +static int keyring_duplicate(struct key *keyring, const struct key *source) +{ + struct keyring_list *sklist, *klist; + unsigned max; + size_t size; + int loop, ret; + + const unsigned limit = + (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key *); + + ret = 0; + + /* find out how many keys are currently linked */ + rcu_read_lock(); + sklist = rcu_dereference(source->payload.subscriptions); + max = 0; + if (sklist) + max = sklist->nkeys; + rcu_read_unlock(); + + /* allocate a new payload and stuff load with key links */ + if (max > 0) { + BUG_ON(max > limit); + + max = (max + 3) & ~3; + if (max > limit) + max = limit; + + ret = -ENOMEM; + size = sizeof(*klist) + sizeof(struct key *) * max; + klist = kmalloc(size, GFP_KERNEL); + if (!klist) + goto error; + + /* set links */ + rcu_read_lock(); + sklist = rcu_dereference(source->payload.subscriptions); + + klist->maxkeys = max; + klist->nkeys = sklist->nkeys; + memcpy(klist->keys, + sklist->keys, + sklist->nkeys * sizeof(struct key *)); + + for (loop = klist->nkeys - 1; loop >= 0; loop--) + atomic_inc(&klist->keys[loop]->usage); + + rcu_read_unlock(); + + rcu_assign_pointer(keyring->payload.subscriptions, klist); + ret = 0; + } + + error: + return ret; + +} /* end keyring_duplicate() */ + /*****************************************************************************/ /* * match keyrings on their name diff --git a/trunk/security/keys/user_defined.c b/trunk/security/keys/user_defined.c index 8e71895b97a7..cbda3b2780a1 100644 --- a/trunk/security/keys/user_defined.c +++ b/trunk/security/keys/user_defined.c @@ -26,6 +26,7 @@ struct key_type key_type_user = { .name = "user", .instantiate = user_instantiate, + .duplicate = user_duplicate, .update = user_update, .match = user_match, .destroy = user_destroy, @@ -67,8 +68,40 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) return ret; } /* end user_instantiate() */ + EXPORT_SYMBOL_GPL(user_instantiate); +/*****************************************************************************/ +/* + * duplicate a user defined key + * - both keys' semaphores are locked against further modification + * - the new key cannot yet be accessed + */ +int user_duplicate(struct key *key, const struct key *source) +{ + struct user_key_payload *upayload, *spayload; + int ret; + + /* just copy the payload */ + ret = -ENOMEM; + upayload = kmalloc(sizeof(*upayload) + source->datalen, GFP_KERNEL); + if (upayload) { + spayload = rcu_dereference(source->payload.data); + BUG_ON(source->datalen != spayload->datalen); + + upayload->datalen = key->datalen = spayload->datalen; + memcpy(upayload->data, spayload->data, key->datalen); + + key->payload.data = upayload; + ret = 0; + } + + return ret; + +} /* end user_duplicate() */ + +EXPORT_SYMBOL_GPL(user_duplicate); + /*****************************************************************************/ /* * dispose of the old data from an updated user defined key diff --git a/trunk/security/selinux/selinuxfs.c b/trunk/security/selinux/selinuxfs.c index e59da6398d44..0e1352a555c8 100644 --- a/trunk/security/selinux/selinuxfs.c +++ b/trunk/security/selinux/selinuxfs.c @@ -376,7 +376,7 @@ static ssize_t selinux_transaction_write(struct file *file, const char __user *b char *data; ssize_t rv; - if (ino >= ARRAY_SIZE(write_op) || !write_op[ino]) + if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino]) return -EINVAL; data = simple_transaction_get(file, buf, size); @@ -1161,7 +1161,7 @@ static int sel_make_avc_files(struct dentry *dir) #endif }; - for (i = 0; i < ARRAY_SIZE(files); i++) { + for (i = 0; i < sizeof (files) / sizeof (files[0]); i++) { struct inode *inode; struct dentry *dentry; diff --git a/trunk/security/selinux/ss/avtab.c b/trunk/security/selinux/ss/avtab.c index d049c7acbc8b..dde094feb20d 100644 --- a/trunk/security/selinux/ss/avtab.c +++ b/trunk/security/selinux/ss/avtab.c @@ -359,7 +359,7 @@ int avtab_read_item(void *fp, u32 vers, struct avtab *a, return -1; } - for (i = 0; i < ARRAY_SIZE(spec_order); i++) { + for (i = 0; i < sizeof(spec_order)/sizeof(u16); i++) { if (val & spec_order[i]) { key.specified = spec_order[i] | enabled; datum.data = le32_to_cpu(buf32[items++]); diff --git a/trunk/security/selinux/ss/policydb.c b/trunk/security/selinux/ss/policydb.c index 0111990ba837..0ac311dc8371 100644 --- a/trunk/security/selinux/ss/policydb.c +++ b/trunk/security/selinux/ss/policydb.c @@ -103,7 +103,7 @@ static struct policydb_compat_info *policydb_lookup_compat(int version) int i; struct policydb_compat_info *info = NULL; - for (i = 0; i < ARRAY_SIZE(policydb_compat); i++) { + for (i = 0; i < sizeof(policydb_compat)/sizeof(*info); i++) { if (policydb_compat[i].version == version) { info = &policydb_compat[i]; break; diff --git a/trunk/sound/oss/ad1848.c b/trunk/sound/oss/ad1848.c index 49796be955f3..3f30c57676c1 100644 --- a/trunk/sound/oss/ad1848.c +++ b/trunk/sound/oss/ad1848.c @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include #include @@ -103,6 +105,9 @@ typedef struct int irq_ok; mixer_ents *mix_devices; int mixer_output_port; + + /* Power management */ + struct pm_dev *pmdev; } ad1848_info; typedef struct ad1848_port_info @@ -196,6 +201,7 @@ static void ad1848_halt(int dev); static void ad1848_halt_input(int dev); static void ad1848_halt_output(int dev); static void ad1848_trigger(int dev, int bits); +static int ad1848_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data); #ifndef EXCLUDE_TIMERS static int ad1848_tmr_install(int dev); @@ -2021,6 +2027,10 @@ int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback, nr_ad1848_devs++; + devc->pmdev = pm_register(PM_ISA_DEV, my_dev, ad1848_pm_callback); + if (devc->pmdev) + devc->pmdev->data = devc; + ad1848_init_hw(devc); if (irq > 0) @@ -2187,6 +2197,9 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int if(mixer>=0) sound_unload_mixerdev(mixer); + if (devc->pmdev) + pm_unregister(devc->pmdev); + nr_ad1848_devs--; for ( ; i < nr_ad1848_devs ; i++) adev_info[i] = adev_info[i+1]; @@ -2798,6 +2811,85 @@ static int ad1848_tmr_install(int dev) } #endif /* EXCLUDE_TIMERS */ +static int ad1848_suspend(ad1848_info *devc) +{ + unsigned long flags; + + spin_lock_irqsave(&devc->lock,flags); + + ad_mute(devc); + + spin_unlock_irqrestore(&devc->lock,flags); + return 0; +} + +static int ad1848_resume(ad1848_info *devc) +{ + int mixer_levels[32], i; + + /* Thinkpad is a bit more of PITA than normal. The BIOS tends to + restore it in a different config to the one we use. Need to + fix this somehow */ + + /* store old mixer levels */ + memcpy(mixer_levels, devc->levels, sizeof (mixer_levels)); + ad1848_init_hw(devc); + + /* restore mixer levels */ + for (i = 0; i < 32; i++) + ad1848_mixer_set(devc, devc->dev_no, mixer_levels[i]); + + if (!devc->subtype) { + static signed char interrupt_bits[12] = { -1, -1, -1, -1, -1, 0x00, -1, 0x08, -1, 0x10, 0x18, 0x20 }; + static char dma_bits[4] = { 1, 2, 0, 3 }; + unsigned long flags; + signed char bits; + char dma2_bit = 0; + + int config_port = devc->base + 0; + + bits = interrupt_bits[devc->irq]; + if (bits == -1) { + printk(KERN_ERR "MSS: Bad IRQ %d\n", devc->irq); + return -1; + } + + spin_lock_irqsave(&devc->lock,flags); + + outb((bits | 0x40), config_port); + + if (devc->dma2 != -1 && devc->dma2 != devc->dma1) + if ( (devc->dma1 == 0 && devc->dma2 == 1) || + (devc->dma1 == 1 && devc->dma2 == 0) || + (devc->dma1 == 3 && devc->dma2 == 0)) + dma2_bit = 0x04; + + outb((bits | dma_bits[devc->dma1] | dma2_bit), config_port); + spin_unlock_irqrestore(&devc->lock,flags); + } + + return 0; +} + +static int ad1848_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + ad1848_info *devc = dev->data; + if (devc) { + DEB(printk("ad1848: pm event received: 0x%x\n", rqst)); + + switch (rqst) { + case PM_SUSPEND: + ad1848_suspend(devc); + break; + case PM_RESUME: + ad1848_resume(devc); + break; + } + } + return 0; +} + + EXPORT_SYMBOL(ad1848_detect); EXPORT_SYMBOL(ad1848_init); EXPORT_SYMBOL(ad1848_unload); diff --git a/trunk/sound/oss/cs4281/cs4281m.c b/trunk/sound/oss/cs4281/cs4281m.c index 46dd41dc2a34..adc689649fe1 100644 --- a/trunk/sound/oss/cs4281/cs4281m.c +++ b/trunk/sound/oss/cs4281/cs4281m.c @@ -298,6 +298,7 @@ struct cs4281_state { struct cs4281_pipeline pl[CS4281_NUMBER_OF_PIPELINES]; }; +#include #include "cs4281pm-24.c" #if CSDEBUG @@ -4255,6 +4256,9 @@ static void __devinit cs4281_InitPM(struct cs4281_state *s) static int __devinit cs4281_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) { +#ifndef NOT_CS4281_PM + struct pm_dev *pmdev; +#endif struct cs4281_state *s; dma_addr_t dma_mask; mm_segment_t fs; @@ -4370,7 +4374,19 @@ static int __devinit cs4281_probe(struct pci_dev *pcidev, } #ifndef NOT_CS4281_PM cs4281_InitPM(s); - s->pm.flags |= CS4281_PM_NOT_REGISTERED; + pmdev = cs_pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), cs4281_pm_callback); + if (pmdev) + { + CS_DBGOUT(CS_INIT | CS_PM, 4, printk(KERN_INFO + "cs4281: probe() pm_register() succeeded (%p).\n", pmdev)); + pmdev->data = s; + } + else + { + CS_DBGOUT(CS_INIT | CS_PM | CS_ERROR, 0, printk(KERN_INFO + "cs4281: probe() pm_register() failed (%p).\n", pmdev)); + s->pm.flags |= CS4281_PM_NOT_REGISTERED; + } #endif pci_set_master(pcidev); // enable bus mastering @@ -4471,6 +4487,9 @@ static int __init cs4281_init_module(void) static void __exit cs4281_cleanup_module(void) { pci_unregister_driver(&cs4281_pci_driver); +#ifndef NOT_CS4281_PM + cs_pm_unregister_all(cs4281_pm_callback); +#endif CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cleanup_cs4281() finished\n")); } diff --git a/trunk/sound/oss/cs4281/cs4281pm-24.c b/trunk/sound/oss/cs4281/cs4281pm-24.c index 90cbd7679534..d2a453aff0aa 100644 --- a/trunk/sound/oss/cs4281/cs4281pm-24.c +++ b/trunk/sound/oss/cs4281/cs4281pm-24.c @@ -27,6 +27,9 @@ #ifndef NOT_CS4281_PM #include +#define cs_pm_register(a, b, c) pm_register((a), (b), (c)); +#define cs_pm_unregister_all(a) pm_unregister_all((a)); + static int cs4281_suspend(struct cs4281_state *s); static int cs4281_resume(struct cs4281_state *s); /* @@ -38,6 +41,42 @@ static int cs4281_resume(struct cs4281_state *s); #define CS4281_SUSPEND_TBL cs4281_suspend_null #define CS4281_RESUME_TBL cs4281_resume_null +static int cs4281_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + struct cs4281_state *state; + + CS_DBGOUT(CS_PM, 2, printk(KERN_INFO + "cs4281: cs4281_pm_callback dev=%p rqst=0x%x state=%p\n", + dev,(unsigned)rqst,data)); + state = (struct cs4281_state *) dev->data; + if (state) { + switch(rqst) { + case PM_SUSPEND: + CS_DBGOUT(CS_PM, 2, printk(KERN_INFO + "cs4281: PM suspend request\n")); + if(cs4281_suspend(state)) + { + CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO + "cs4281: PM suspend request refused\n")); + return 1; + } + break; + case PM_RESUME: + CS_DBGOUT(CS_PM, 2, printk(KERN_INFO + "cs4281: PM resume request\n")); + if(cs4281_resume(state)) + { + CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO + "cs4281: PM resume request refused\n")); + return 1; + } + break; + } + } + + return 0; +} + #else /* CS4281_PM */ #define CS4281_SUSPEND_TBL cs4281_suspend_null #define CS4281_RESUME_TBL cs4281_resume_null diff --git a/trunk/sound/oss/cs46xx.c b/trunk/sound/oss/cs46xx.c index 0da4d93f04a6..cb998e8c0fdd 100644 --- a/trunk/sound/oss/cs46xx.c +++ b/trunk/sound/oss/cs46xx.c @@ -391,6 +391,10 @@ static void cs461x_clear_serial_FIFOs(struct cs_card *card, int type); static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state); static int cs46xx_resume_tbl(struct pci_dev *pcidev); +#ifndef CS46XX_ACPI_SUPPORT +static int cs46xx_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data); +#endif + #if CSDEBUG /* DEBUG ROUTINES */ @@ -5316,6 +5320,7 @@ static const char fndmsg[] = KERN_INFO "cs46xx: Found %d audio device(s).\n"; static int __devinit cs46xx_probe(struct pci_dev *pci_dev, const struct pci_device_id *pciid) { + struct pm_dev *pmdev; int i,j; u16 ss_card, ss_vendor; struct cs_card *card; @@ -5525,6 +5530,22 @@ static int __devinit cs46xx_probe(struct pci_dev *pci_dev, PCI_SET_DMA_MASK(pci_dev, dma_mask); list_add(&card->list, &cs46xx_devs); + pmdev = cs_pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), cs46xx_pm_callback); + if (pmdev) + { + CS_DBGOUT(CS_INIT | CS_PM, 4, printk(KERN_INFO + "cs46xx: probe() pm_register() succeeded (%p).\n", + pmdev)); + pmdev->data = card; + } + else + { + CS_DBGOUT(CS_INIT | CS_PM | CS_ERROR, 2, printk(KERN_INFO + "cs46xx: probe() pm_register() failed (%p).\n", + pmdev)); + card->pm.flags |= CS46XX_PM_NOT_REGISTERED; + } + CS_DBGOUT(CS_PM, 9, printk(KERN_INFO "cs46xx: pm.flags=0x%x card=%p\n", (unsigned)card->pm.flags,card)); @@ -5706,6 +5727,7 @@ static int __init cs46xx_init_module(void) static void __exit cs46xx_cleanup_module(void) { pci_unregister_driver(&cs46xx_pci_driver); + cs_pm_unregister_all(cs46xx_pm_callback); CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cleanup_cs46xx() finished\n")); } @@ -5713,6 +5735,44 @@ static void __exit cs46xx_cleanup_module(void) module_init(cs46xx_init_module); module_exit(cs46xx_cleanup_module); +#ifndef CS46XX_ACPI_SUPPORT +static int cs46xx_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + struct cs_card *card; + + CS_DBGOUT(CS_PM, 2, printk(KERN_INFO + "cs46xx: cs46xx_pm_callback dev=%p rqst=0x%x card=%p\n", + dev,(unsigned)rqst,data)); + card = (struct cs_card *) dev->data; + if (card) { + switch(rqst) { + case PM_SUSPEND: + CS_DBGOUT(CS_PM, 2, printk(KERN_INFO + "cs46xx: PM suspend request\n")); + if(cs46xx_suspend(card, PMSG_SUSPEND)) + { + CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO + "cs46xx: PM suspend request refused\n")); + return 1; + } + break; + case PM_RESUME: + CS_DBGOUT(CS_PM, 2, printk(KERN_INFO + "cs46xx: PM resume request\n")); + if(cs46xx_resume(card)) + { + CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO + "cs46xx: PM resume request refused\n")); + return 1; + } + break; + } + } + + return 0; +} +#endif + #if CS46XX_ACPI_SUPPORT static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state) { diff --git a/trunk/sound/oss/cs46xxpm-24.h b/trunk/sound/oss/cs46xxpm-24.h index ad82db84d013..e220bd7240f1 100644 --- a/trunk/sound/oss/cs46xxpm-24.h +++ b/trunk/sound/oss/cs46xxpm-24.h @@ -38,9 +38,13 @@ */ static int cs46xx_suspend_tbl(struct pci_dev *pcidev, pm_message_t state); static int cs46xx_resume_tbl(struct pci_dev *pcidev); +#define cs_pm_register(a, b, c) NULL +#define cs_pm_unregister_all(a) #define CS46XX_SUSPEND_TBL cs46xx_suspend_tbl #define CS46XX_RESUME_TBL cs46xx_resume_tbl #else +#define cs_pm_register(a, b, c) pm_register((a), (b), (c)); +#define cs_pm_unregister_all(a) pm_unregister_all((a)); #define CS46XX_SUSPEND_TBL cs46xx_null #define CS46XX_RESUME_TBL cs46xx_null #endif diff --git a/trunk/sound/oss/maestro.c b/trunk/sound/oss/maestro.c index f9ac5b16f61a..3abd3541cbc7 100644 --- a/trunk/sound/oss/maestro.c +++ b/trunk/sound/oss/maestro.c @@ -230,6 +230,10 @@ #include #include +#include +#include +static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d); + #include "maestro.h" static struct pci_driver maestro_pci_driver; @@ -3400,6 +3404,7 @@ maestro_probe(struct pci_dev *pcidev,const struct pci_device_id *pdid) int i, ret; struct ess_card *card; struct ess_state *ess; + struct pm_dev *pmdev; int num = 0; /* when built into the kernel, we only print version if device is found */ @@ -3445,6 +3450,11 @@ maestro_probe(struct pci_dev *pcidev,const struct pci_device_id *pdid) memset(card, 0, sizeof(*card)); card->pcidev = pcidev; + pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), + maestro_pm_callback); + if (pmdev) + pmdev->data = card; + card->iobase = iobase; card->card_type = card_type; card->irq = pcidev->irq; @@ -3660,6 +3670,7 @@ static int maestro_notifier(struct notifier_block *nb, unsigned long event, void static void cleanup_maestro(void) { M_printk("maestro: unloading\n"); pci_unregister_driver(&maestro_pci_driver); + pm_unregister_all(maestro_pm_callback); unregister_reboot_notifier(&maestro_nb); } @@ -3680,5 +3691,143 @@ check_suspend(struct ess_card *card) current->state = TASK_RUNNING; } +static int +maestro_suspend(struct ess_card *card) +{ + unsigned long flags; + int i,j; + + spin_lock_irqsave(&card->lock,flags); /* over-kill */ + + M_printk("maestro: apm in dev %p\n",card); + + /* we have to read from the apu regs, need + to power it up */ + maestro_power(card,ACPI_D0); + + for(i=0;ichannels[i]; + + if(s->dev_audio == -1) + continue; + + M_printk("maestro: stopping apus for device %d\n",i); + stop_dac(s); + stop_adc(s); + for(j=0;j<6;j++) + card->apu_map[s->apu[j]][5]=apu_get_register(s,j,5); + + } + + /* get rid of interrupts? */ + if( card->dsps_open > 0) + stop_bob(&card->channels[0]); + + card->in_suspend++; + + spin_unlock_irqrestore(&card->lock,flags); + + /* we trust in the bios to power down the chip on suspend. + * XXX I'm also not sure that in_suspend will protect + * against all reg accesses from here on out. + */ + return 0; +} +static int +maestro_resume(struct ess_card *card) +{ + unsigned long flags; + int i; + + spin_lock_irqsave(&card->lock,flags); /* over-kill */ + + card->in_suspend = 0; + + M_printk("maestro: resuming card at %p\n",card); + + /* restore all our config */ + maestro_config(card); + /* need to restore the base pointers.. */ + if(card->dmapages) + set_base_registers(&card->channels[0],card->dmapages); + + mixer_push_state(card); + + /* set each channels' apu control registers before + * restoring audio + */ + for(i=0;ichannels[i]; + int chan,reg; + + if(s->dev_audio == -1) + continue; + + for(chan = 0 ; chan < 6 ; chan++) { + wave_set_register(s,s->apu[chan]<<3,s->apu_base[chan]); + for(reg = 1 ; reg < NR_APU_REGS ; reg++) + apu_set_register(s,chan,reg,s->card->apu_map[s->apu[chan]][reg]); + } + for(chan = 0 ; chan < 6 ; chan++) + apu_set_register(s,chan,0,s->card->apu_map[s->apu[chan]][0] & 0xFF0F); + } + + /* now we flip on the music */ + + if( card->dsps_open <= 0) { + /* this card's idle */ + maestro_power(card,ACPI_D2); + } else { + /* ok, we're actually playing things on + this card */ + maestro_power(card,ACPI_D0); + start_bob(&card->channels[0]); + for(i=0;ichannels[i]; + + /* these use the apu_mode, and can handle + spurious calls */ + start_dac(s); + start_adc(s); + } + } + + spin_unlock_irqrestore(&card->lock,flags); + + /* all right, we think things are ready, + wake up people who were using the device + when we suspended */ + wake_up(&(card->suspend_queue)); + + return 0; +} + +int +maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data) +{ + struct ess_card *card = (struct ess_card*) dev->data; + + if ( ! card ) goto out; + + M_printk("maestro: pm event 0x%x received for card %p\n", rqst, card); + + switch (rqst) { + case PM_SUSPEND: + maestro_suspend(card); + break; + case PM_RESUME: + maestro_resume(card); + break; + /* + * we'd also like to find out about + * power level changes because some biosen + * do mean things to the maestro when they + * change their power state. + */ + } +out: + return 0; +} + module_init(init_maestro); module_exit(cleanup_maestro); diff --git a/trunk/sound/oss/nm256_audio.c b/trunk/sound/oss/nm256_audio.c index 42d8f05689c2..0ce2c404a730 100644 --- a/trunk/sound/oss/nm256_audio.c +++ b/trunk/sound/oss/nm256_audio.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include "sound_config.h" @@ -47,6 +49,7 @@ static int nm256_grabInterrupt (struct nm256_info *card); static int nm256_releaseInterrupt (struct nm256_info *card); static irqreturn_t nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy); static irqreturn_t nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy); +static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data); /* These belong in linux/pci.h. */ #define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005 @@ -989,6 +992,15 @@ nm256_install_mixer (struct nm256_info *card) return 0; } +/* Perform a full reset on the hardware; this is invoked when an APM + resume event occurs. */ +static void +nm256_full_reset (struct nm256_info *card) +{ + nm256_initHw (card); + ac97_reset (&(card->mdev)); +} + /* * See if the signature left by the NM256 BIOS is intact; if so, we use * the associated address as the end of our audio buffer in the video @@ -1041,6 +1053,7 @@ static int __devinit nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) { struct nm256_info *card; + struct pm_dev *pmdev; int x; if (pci_enable_device(pcidev)) @@ -1221,10 +1234,43 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) nm256_install_mixer (card); + pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), handle_pm_event); + if (pmdev) + pmdev->data = card; + return 1; } +/* + * PM event handler, so the card is properly reinitialized after a power + * event. + */ +static int +handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data) +{ + struct nm256_info *crd = (struct nm256_info*) dev->data; + if (crd) { + switch (rqst) { + case PM_SUSPEND: + break; + case PM_RESUME: + { + int playing = crd->playing; + nm256_full_reset (crd); + /* + * A little ugly, but that's ok; pretend the + * block we were playing is done. + */ + if (playing) + DMAbuf_outputintr (crd->dev_for_play, 1); + } + break; + } + } + return 0; +} + static int __devinit nm256_probe(struct pci_dev *pcidev,const struct pci_device_id *pciid) { @@ -1650,6 +1696,7 @@ static int __init do_init_nm256(void) static void __exit cleanup_nm256 (void) { pci_unregister_driver(&nm256_pci_driver); + pm_unregister_all (&handle_pm_event); } module_init(do_init_nm256); diff --git a/trunk/sound/oss/opl3sa2.c b/trunk/sound/oss/opl3sa2.c index 5cecdbcbea9d..cd41d0e4706a 100644 --- a/trunk/sound/oss/opl3sa2.c +++ b/trunk/sound/oss/opl3sa2.c @@ -69,6 +69,8 @@ #include #include #include +#include +#include #include "sound_config.h" #include "ad1848.h" @@ -136,6 +138,10 @@ typedef struct { /* PnP Stuff */ struct pnp_dev* pdev; int activated; /* Whether said devices have been activated */ +#endif +#ifdef CONFIG_PM_LEGACY + unsigned int in_suspend; + struct pm_dev *pmdev; #endif unsigned int card; int chipset; /* What's my version(s)? */ @@ -335,6 +341,22 @@ static void opl3sa2_mixer_reset(opl3sa2_state_t* devc) } } +/* Currently only used for power management */ +#ifdef CONFIG_PM_LEGACY +static void opl3sa2_mixer_restore(opl3sa2_state_t* devc) +{ + if (devc) { + opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r); + opl3sa2_set_mic(devc, devc->mic); + + if (devc->chipset == CHIPSET_OPL3SA3) { + opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r); + opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r); + } + } +} +#endif /* CONFIG_PM_LEGACY */ + static inline void arg_to_vol_mono(unsigned int vol, int* value) { int left; @@ -810,6 +832,84 @@ static struct pnp_driver opl3sa2_driver = { /* End of component functions */ +#ifdef CONFIG_PM_LEGACY + +static DEFINE_SPINLOCK(opl3sa2_lock); + +/* Power Management support functions */ +static int opl3sa2_suspend(struct pm_dev *pdev, unsigned int pm_mode) +{ + unsigned long flags; + opl3sa2_state_t *p; + + if (!pdev) + return -EINVAL; + + spin_lock_irqsave(&opl3sa2_lock,flags); + + p = (opl3sa2_state_t *) pdev->data; + switch (pm_mode) { + case 1: + pm_mode = OPL3SA2_PM_MODE1; + break; + case 2: + pm_mode = OPL3SA2_PM_MODE2; + break; + case 3: + pm_mode = OPL3SA2_PM_MODE3; + break; + default: + /* we don't know howto handle this... */ + spin_unlock_irqrestore(&opl3sa2_lock, flags); + return -EBUSY; + } + + p->in_suspend = 1; + + /* its supposed to automute before suspending, so we won't bother */ + opl3sa2_write(p->cfg_port, OPL3SA2_PM, pm_mode); + /* wait a while for the clock oscillator to stabilise */ + mdelay(10); + + spin_unlock_irqrestore(&opl3sa2_lock,flags); + return 0; +} + +static int opl3sa2_resume(struct pm_dev *pdev) +{ + unsigned long flags; + opl3sa2_state_t *p; + + if (!pdev) + return -EINVAL; + + p = (opl3sa2_state_t *) pdev->data; + spin_lock_irqsave(&opl3sa2_lock,flags); + + /* I don't think this is necessary */ + opl3sa2_write(p->cfg_port, OPL3SA2_PM, OPL3SA2_PM_MODE0); + opl3sa2_mixer_restore(p); + p->in_suspend = 0; + + spin_unlock_irqrestore(&opl3sa2_lock,flags); + return 0; +} + +static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data) +{ + unsigned long mode = (unsigned long)data; + + switch (rqst) { + case PM_SUSPEND: + return opl3sa2_suspend(pdev, mode); + + case PM_RESUME: + return opl3sa2_resume(pdev); + } + return 0; +} +#endif /* CONFIG_PM_LEGACY */ + /* * Install OPL3-SA2 based card(s). * @@ -921,6 +1021,12 @@ static int __init init_opl3sa2(void) /* ewww =) */ opl3sa2_state[card].card = card; +#ifdef CONFIG_PM_LEGACY + /* register our power management capabilities */ + opl3sa2_state[card].pmdev = pm_register(PM_ISA_DEV, card, opl3sa2_pm_callback); + if (opl3sa2_state[card].pmdev) + opl3sa2_state[card].pmdev->data = &opl3sa2_state[card]; +#endif /* CONFIG_PM_LEGACY */ /* * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and @@ -977,6 +1083,10 @@ static void __exit cleanup_opl3sa2(void) int card; for(card = 0; card < opl3sa2_cards_num; card++) { +#ifdef CONFIG_PM_LEGACY + if (opl3sa2_state[card].pmdev) + pm_unregister(opl3sa2_state[card].pmdev); +#endif if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) { unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu); }