]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 7 Feb 2007 16:09:00 +0000 (08:09 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Wed, 7 Feb 2007 16:09:00 +0000 (08:09 -0800)
* git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw: (57 commits)
  [GFS2] make gfs2_writepages() static
  [GFS2] Unlock page on prepare_write try lock failure
  [GFS2] nfsd readdirplus assertion failure
  [DLM] fix softlockup in dlm_recv
  [DLM] zero new user lvbs
  [DLM/GFS2] indent help text
  [GFS2] Fix unlink deadlocks
  [GFS2] Put back semaphore to avoid umount problem
  [GFS2] more CURRENT_TIME_SEC
  [GFS2/DLM] fix GFS2 circular dependency
  [GFS2/DLM] use sysfs
  [GFS2] make lock_dlm drop_count tunable in sysfs
  [GFS2] increase default lock limit
  [GFS2] Fix list corruption in lops.c
  [GFS2] Fix recursive locking attempt with NFS
  [DLM] can miss clearing resend flag
  [DLM] saved dlm message can be dropped
  [DLM] Make sock_sem into a mutex
  [GFS2] Fix typo in glock.c
  [GFS2] use CURRENT_TIME_SEC instead of get_seconds in gfs2
  ...

414 files changed:
Documentation/s390/Debugging390.txt
MAINTAINERS
Makefile
arch/ia64/Kconfig
arch/ia64/hp/common/hwsw_iommu.c
arch/ia64/kernel/crash.c
arch/ia64/kernel/crash_dump.c
arch/ia64/kernel/efi.c
arch/ia64/kernel/entry.S
arch/ia64/kernel/iosapic.c
arch/ia64/kernel/machine_kexec.c
arch/ia64/kernel/process.c
arch/ia64/kernel/ptrace.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/mm/init.c
arch/ia64/sn/kernel/huberror.c
arch/mips/Kconfig
arch/mips/Kconfig.debug
arch/mips/arc/identify.c
arch/mips/arc/memory.c
arch/mips/au1000/common/irq.c
arch/mips/au1000/common/pci.c
arch/mips/au1000/common/prom.c
arch/mips/au1000/common/setup.c
arch/mips/au1000/pb1100/board_setup.c
arch/mips/au1000/pb1200/irqmap.c
arch/mips/basler/excite/excite_irq.c
arch/mips/cobalt/irq.c
arch/mips/cobalt/setup.c
arch/mips/ddb5xxx/common/prom.c
arch/mips/ddb5xxx/ddb5477/irq.c
arch/mips/ddb5xxx/ddb5477/irq_5477.c
arch/mips/dec/ioasic-irq.c
arch/mips/dec/kn02-irq.c
arch/mips/dec/prom/memory.c
arch/mips/dec/setup.c
arch/mips/emma2rh/common/irq_emma2rh.c
arch/mips/emma2rh/markeins/irq.c
arch/mips/emma2rh/markeins/irq_markeins.c
arch/mips/gt64120/ev64120/irq.c
arch/mips/gt64120/ev64120/setup.c
arch/mips/gt64120/momenco_ocelot/dbg_io.c
arch/mips/gt64120/momenco_ocelot/irq.c
arch/mips/gt64120/momenco_ocelot/prom.c
arch/mips/gt64120/wrppmc/irq.c
arch/mips/gt64120/wrppmc/setup.c
arch/mips/jazz/irq.c
arch/mips/jmr3927/common/prom.c
arch/mips/jmr3927/rbhma3100/irq.c
arch/mips/jmr3927/rbhma3100/setup.c
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/gdb-stub.c
arch/mips/kernel/head.S
arch/mips/kernel/i8259.c
arch/mips/kernel/irixelf.c
arch/mips/kernel/irq-msc01.c
arch/mips/kernel/irq-mv6434x.c
arch/mips/kernel/irq-rm7000.c
arch/mips/kernel/irq-rm9000.c
arch/mips/kernel/irq_cpu.c
arch/mips/kernel/linux32.c
arch/mips/kernel/mips-mt.c
arch/mips/kernel/proc.c
arch/mips/kernel/process.c
arch/mips/kernel/r4k_fpu.S
arch/mips/kernel/rtlx.c
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal_n32.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/smtc.c
arch/mips/kernel/sysirix.c
arch/mips/kernel/vpe.c
arch/mips/lasat/interrupt.c
arch/mips/lasat/prom.c
arch/mips/lib-32/Makefile
arch/mips/lib-64/Makefile
arch/mips/lib-64/memset.S [deleted file]
arch/mips/lib/Makefile
arch/mips/lib/memset.S [moved from arch/mips/lib-32/memset.S with 85% similarity]
arch/mips/lib/uncached.c
arch/mips/mips-boards/atlas/atlas_int.c
arch/mips/mips-boards/generic/memory.c
arch/mips/mips-boards/malta/malta_int.c
arch/mips/mips-boards/sead/sead_int.c
arch/mips/mips-boards/sim/sim_int.c
arch/mips/mips-boards/sim/sim_mem.c
arch/mips/mm/init.c
arch/mips/momentum/jaguar_atx/Makefile
arch/mips/momentum/jaguar_atx/irq.c
arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
arch/mips/momentum/jaguar_atx/platform.c [new file with mode: 0644]
arch/mips/momentum/jaguar_atx/prom.c
arch/mips/momentum/ocelot_3/irq.c
arch/mips/momentum/ocelot_3/prom.c
arch/mips/momentum/ocelot_c/cpci-irq.c
arch/mips/momentum/ocelot_c/dbg_io.c
arch/mips/momentum/ocelot_c/irq.c
arch/mips/momentum/ocelot_c/prom.c
arch/mips/momentum/ocelot_c/uart-irq.c
arch/mips/momentum/ocelot_g/dbg_io.c
arch/mips/momentum/ocelot_g/irq.c
arch/mips/momentum/ocelot_g/prom.c
arch/mips/oprofile/Kconfig
arch/mips/pci/fixup-vr4133.c
arch/mips/philips/pnx8550/common/int.c
arch/mips/philips/pnx8550/common/prom.c
arch/mips/pmc-sierra/yosemite/dbg_io.c
arch/mips/pmc-sierra/yosemite/irq.c
arch/mips/pmc-sierra/yosemite/prom.c
arch/mips/pmc-sierra/yosemite/setup.c
arch/mips/qemu/q-mem.c
arch/mips/sgi-ip22/ip22-eisa.c
arch/mips/sgi-ip22/ip22-int.c
arch/mips/sgi-ip22/ip22-mc.c
arch/mips/sgi-ip27/ip27-irq.c
arch/mips/sgi-ip27/ip27-memory.c
arch/mips/sgi-ip27/ip27-timer.c
arch/mips/sgi-ip32/ip32-irq.c
arch/mips/sgi-ip32/ip32-memory.c
arch/mips/sibyte/bcm1480/irq.c
arch/mips/sibyte/cfe/setup.c
arch/mips/sibyte/sb1250/irq.c
arch/mips/sibyte/sb1250/prom.c
arch/mips/sni/irq.c
arch/mips/sni/sniprom.c
arch/mips/tx4927/common/tx4927_irq.c
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c
arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c
arch/mips/tx4938/common/irq.c
arch/mips/tx4938/toshiba_rbtx4938/irq.c
arch/mips/tx4938/toshiba_rbtx4938/prom.c
arch/mips/vr41xx/common/icu.c
arch/mips/vr41xx/common/init.c
arch/mips/vr41xx/common/irq.c
arch/mips/vr41xx/nec-cmbvr4133/irq.c
arch/s390/Kconfig
arch/s390/appldata/appldata_base.c
arch/s390/appldata/appldata_mem.c
arch/s390/appldata/appldata_net_sum.c
arch/s390/crypto/Kconfig [new file with mode: 0644]
arch/s390/crypto/Makefile
arch/s390/crypto/aes_s390.c
arch/s390/crypto/crypt_s390.h
arch/s390/crypto/crypt_s390_query.c [deleted file]
arch/s390/crypto/des_check_key.c
arch/s390/crypto/des_s390.c
arch/s390/crypto/prng.c [new file with mode: 0644]
arch/s390/crypto/sha1_s390.c
arch/s390/crypto/sha256_s390.c
arch/s390/defconfig
arch/s390/hypfs/Makefile
arch/s390/hypfs/hypfs.h
arch/s390/hypfs/hypfs_diag.h [deleted file]
arch/s390/hypfs/hypfs_vm.c [new file with mode: 0644]
arch/s390/hypfs/inode.c
arch/s390/kernel/Makefile
arch/s390/kernel/base.S [new file with mode: 0644]
arch/s390/kernel/binfmt_elf32.c
arch/s390/kernel/compat_exec_domain.c
arch/s390/kernel/compat_linux.c
arch/s390/kernel/compat_linux.h
arch/s390/kernel/compat_signal.c
arch/s390/kernel/cpcmd.c
arch/s390/kernel/crash.c
arch/s390/kernel/debug.c
arch/s390/kernel/early.c [new file with mode: 0644]
arch/s390/kernel/ebcdic.c
arch/s390/kernel/head31.S
arch/s390/kernel/head64.S
arch/s390/kernel/ipl.c
arch/s390/kernel/irq.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/module.c
arch/s390/kernel/process.c
arch/s390/kernel/profile.c [deleted file]
arch/s390/kernel/ptrace.c
arch/s390/kernel/reset.S [deleted file]
arch/s390/kernel/s390_ext.c
arch/s390/kernel/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/smp.c
arch/s390/kernel/stacktrace.c
arch/s390/kernel/time.c
arch/s390/kernel/traps.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kernel/vtime.c
arch/s390/lib/Makefile
arch/s390/lib/delay.c
arch/s390/lib/qrnnd.S [new file with mode: 0644]
arch/s390/lib/uaccess.h [new file with mode: 0644]
arch/s390/lib/uaccess_mvcos.c
arch/s390/lib/uaccess_pt.c
arch/s390/lib/uaccess_std.c
arch/s390/math-emu/Makefile
arch/s390/math-emu/math.c
arch/s390/math-emu/qrnnd.S [deleted file]
arch/s390/mm/cmm.c
arch/s390/mm/extmem.c
arch/s390/mm/fault.c
arch/s390/mm/init.c
arch/s390/mm/vmem.c
arch/x86_64/kernel/pci-swiotlb.c
crypto/Kconfig
drivers/crypto/Kconfig
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-core.c
drivers/hid/hid-debug.c [new file with mode: 0644]
drivers/hid/hid-input.c
drivers/infiniband/core/addr.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/hw/amso1100/c2_cq.c
drivers/infiniband/hw/ehca/ehca_classes.h
drivers/infiniband/hw/ehca/ehca_cq.c
drivers/infiniband/hw/ehca/ehca_iverbs.h
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/ehca/ehca_qp.c
drivers/infiniband/hw/ehca/ehca_reqs.c
drivers/infiniband/hw/ehca/ehca_uverbs.c
drivers/infiniband/hw/ipath/ipath_qp.c
drivers/infiniband/hw/ipath/ipath_rc.c
drivers/infiniband/hw/ipath/ipath_ruc.c
drivers/infiniband/hw/ipath/ipath_uc.c
drivers/infiniband/hw/ipath/ipath_ud.c
drivers/infiniband/hw/mthca/mthca_cmd.c
drivers/infiniband/hw/mthca/mthca_cq.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h
drivers/misc/tifm_7xx1.c
drivers/misc/tifm_core.c
drivers/mmc/at91_mci.c
drivers/mmc/au1xmmc.c
drivers/mmc/imxmmc.c
drivers/mmc/mmc.c
drivers/mmc/mmc_block.c
drivers/mmc/mmc_queue.c
drivers/mmc/mmc_sysfs.c
drivers/mmc/mmci.c
drivers/mmc/omap.c
drivers/mmc/pxamci.c
drivers/mmc/sdhci.c
drivers/mmc/sdhci.h
drivers/mmc/tifm_sd.c
drivers/mmc/wbsd.c
drivers/mmc/wbsd.h
drivers/s390/Kconfig
drivers/s390/Makefile
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_eer.c
drivers/s390/block/dasd_erp.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_proc.c
drivers/s390/block/dcssblk.c
drivers/s390/char/Makefile
drivers/s390/char/con3215.c
drivers/s390/char/con3270.c
drivers/s390/char/defkeymap.c
drivers/s390/char/fs3270.c
drivers/s390/char/keyboard.c
drivers/s390/char/monwriter.c
drivers/s390/char/raw3270.c
drivers/s390/char/sclp.c
drivers/s390/char/sclp.h
drivers/s390/char/sclp_con.c
drivers/s390/char/sclp_cpi.c
drivers/s390/char/sclp_info.c [new file with mode: 0644]
drivers/s390/char/sclp_rw.c
drivers/s390/char/sclp_tty.c
drivers/s390/char/sclp_vt220.c
drivers/s390/char/tape.h
drivers/s390/char/tape_3590.c
drivers/s390/char/tape_3590.h
drivers/s390/char/tape_block.c
drivers/s390/char/tape_char.c
drivers/s390/char/tape_core.c
drivers/s390/char/tty3270.c
drivers/s390/char/vmlogrdr.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/cio.c
drivers/s390/cio/cmf.c
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/device.h
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/device_status.c
drivers/s390/cio/qdio.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_pcica.c
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/net/claw.c
drivers/s390/net/ctcmain.c
drivers/s390/net/cu3088.c
drivers/s390/net/lcs.c
drivers/s390/net/netiucv.c
drivers/s390/net/qeth_eddp.c
drivers/s390/net/qeth_main.c
drivers/s390/net/qeth_sys.c
drivers/s390/s390mach.c
drivers/s390/s390mach.h
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_dbf.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/sysinfo.c
drivers/usb/input/Kconfig
drivers/usb/input/Makefile
drivers/usb/input/hid-core.c
drivers/usb/input/hid-ff.c
drivers/usb/input/hid-plff.c [new file with mode: 0644]
fs/cifs/CHANGES
fs/cifs/cifsfs.c
fs/cifs/file.c
fs/cifs/readdir.c
fs/cifs/smbdes.c
fs/ocfs2/journal.h
include/asm-ia64/dma.h
include/asm-ia64/esi.h
include/asm-ia64/meminit.h
include/asm-ia64/pgalloc.h
include/asm-ia64/swiotlb.h [new file with mode: 0644]
include/asm-ia64/thread_info.h
include/asm-ia64/unistd.h
include/asm-mips/bootinfo.h
include/asm-mips/ddb5xxx/ddb5477.h
include/asm-mips/dec/interrupts.h
include/asm-mips/dma.h
include/asm-mips/emma2rh/emma2rh.h
include/asm-mips/emma2rh/markeins.h
include/asm-mips/i8259.h
include/asm-mips/io.h
include/asm-mips/irq.h
include/asm-mips/irq_cpu.h
include/asm-mips/mach-au1x00/au1000.h
include/asm-mips/mach-cobalt/cobalt.h
include/asm-mips/mach-emma2rh/irq.h
include/asm-mips/mach-generic/irq.h
include/asm-mips/mach-mips/irq.h
include/asm-mips/mach-vr41xx/irq.h [new file with mode: 0644]
include/asm-mips/mips-boards/atlasint.h
include/asm-mips/mips-boards/maltaint.h
include/asm-mips/mips-boards/prom.h
include/asm-mips/mips-boards/seadint.h
include/asm-mips/mips-boards/simint.h
include/asm-mips/mipsmtregs.h
include/asm-mips/page.h
include/asm-mips/rtlx.h
include/asm-mips/sections.h
include/asm-mips/sgi/ip22.h
include/asm-mips/smtc_ipi.h
include/asm-mips/uaccess.h
include/asm-mips/vr41xx/cmbvr4133.h
include/asm-s390/compat.h
include/asm-s390/etr.h [new file with mode: 0644]
include/asm-s390/hardirq.h
include/asm-s390/io.h
include/asm-s390/kdebug.h
include/asm-s390/lowcore.h
include/asm-s390/mmu_context.h
include/asm-s390/pgalloc.h
include/asm-s390/pgtable.h
include/asm-s390/processor.h
include/asm-s390/ptrace.h
include/asm-s390/reset.h
include/asm-s390/sclp.h [new file with mode: 0644]
include/asm-s390/sections.h
include/asm-s390/setup.h
include/asm-s390/sfp-util.h [moved from arch/s390/math-emu/sfp-util.h with 91% similarity]
include/asm-s390/smp.h
include/asm-s390/system.h
include/asm-s390/tape390.h
include/asm-s390/timer.h
include/asm-s390/timex.h
include/asm-s390/tlbflush.h
include/asm-s390/uaccess.h
include/asm-x86_64/swiotlb.h
include/linux/hid-debug.h
include/linux/hid.h
include/linux/mmc/card.h
include/linux/mmc/host.h
include/linux/mmc/mmc.h
include/linux/mmc/protocol.h
include/linux/pci_ids.h
include/linux/tifm.h
include/rdma/ib_user_mad.h
include/rdma/ib_verbs.h
lib/swiotlb.c
scripts/Kbuild.include
scripts/gen_initramfs_list.sh
scripts/makelst
security/keys/key.c

index 3f9ddbc23b27111db424af21d7c0b92cc34f9e68..0993969609cf497e50232847aa319716a7b3663b 100644 (file)
@@ -480,7 +480,7 @@ r2       argument 0 / return value 0                call-clobbered
 r3       argument 1 / return value 1 (if long long) call-clobbered
 r4       argument 2                                 call-clobbered
 r5       argument 3                                 call-clobbered
-r6      argument 5                                 saved
+r6      argument 4                                 saved
 r7       pointer-to arguments 5 to ...              saved      
 r8       this & that                                saved
 r9       this & that                                saved
index 0ad8803a0c7555ae3667846d2445ea9810a6802b..16c0e15b5785699b9563679140c98f5760dc03b8 100644 (file)
@@ -2791,7 +2791,7 @@ M:        schwidefsky@de.ibm.com
 P:     Heiko Carstens
 M:     heiko.carstens@de.ibm.com
 M:     linux390@de.ibm.com
-L:     linux-390@vm.marist.edu
+L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
 
@@ -2799,7 +2799,7 @@ S390 NETWORK DRIVERS
 P:     Frank Pavlic
 M:     fpavlic@de.ibm.com
 M:     linux390@de.ibm.com
-L:     linux-390@vm.marist.edu
+L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
 
@@ -2807,7 +2807,7 @@ S390 ZFCP DRIVER
 P:     Swen Schillig
 M:     swen@vnet.ibm.com
 M:     linux390@de.ibm.com
-L:     linux-390@vm.marist.edu
+L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
 
@@ -3647,7 +3647,7 @@ S:        Maintained
 W83L51xD SD/MMC CARD INTERFACE DRIVER
 P:     Pierre Ossman
 M:     drzeus-wbsd@drzeus.cx
-L:     wbsd-devel@list.drzeus.cx
+L:     linux-kernel@vger.kernel.org
 W:     http://projects.drzeus.cx/wbsd
 S:     Maintained
 
index 7e2750f4ca707a8f009987810d6756a869128f6a..cdeda68cf2aa9082571366837a504fe80ef6c40e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -776,7 +776,7 @@ $(vmlinux-dirs): prepare scripts
 #        $(EXTRAVERSION)               eg, -rc6
 #      $(localver-full)
 #        $(localver)
-#          localversion*               (all localversion* files)
+#          localversion*               (files without backups, containing '~')
 #          $(CONFIG_LOCALVERSION)      (from kernel config setting)
 #        $(localver-auto)              (only if CONFIG_LOCALVERSION_AUTO is set)
 #          ./scripts/setlocalversion   (SCM tag, if one exists)
@@ -787,17 +787,12 @@ $(vmlinux-dirs): prepare scripts
 # moment, only git is supported but other SCMs can edit the script
 # scripts/setlocalversion and add the appropriate checks as needed.
 
-nullstring :=
-space      := $(nullstring) # end of line
+pattern = ".*/localversion[^~]*"
+string  = $(shell cat /dev/null \
+          `find $(objtree) $(srctree) -maxdepth 1 -regex $(pattern) | sort`)
 
-___localver = $(objtree)/localversion* $(srctree)/localversion*
-__localver  = $(sort $(wildcard $(___localver)))
-# skip backup files (containing '~')
-_localver = $(foreach f, $(__localver), $(if $(findstring ~, $(f)),,$(f)))
-
-localver = $(subst $(space),, \
-          $(shell cat /dev/null $(_localver)) \
-          $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
+localver = $(subst $(space),, $(string) \
+                             $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
 
 # If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
 # and if the SCM is know a tag from the SCM is appended.
index fcacfe291b9b7450b5537ec8cbb0aab258e92f5e..f1d2899e9a629763173afffb8d86766a5fac08fc 100644 (file)
@@ -11,6 +11,8 @@ menu "Processor type and features"
 
 config IA64
        bool
+       select PCI if (!IA64_HP_SIM)
+       select ACPI if (!IA64_HP_SIM)
        default y
        help
          The Itanium Processor Family is Intel's 64-bit successor to
@@ -28,7 +30,6 @@ config MMU
 
 config SWIOTLB
        bool
-       default y
 
 config RWSEM_XCHGADD_ALGORITHM
        bool
@@ -84,10 +85,9 @@ choice
 
 config IA64_GENERIC
        bool "generic"
-       select ACPI
-       select PCI
        select NUMA
        select ACPI_NUMA
+       select SWIOTLB
        help
          This selects the system type of your hardware.  A "generic" kernel
          will run on any supported IA-64 system.  However, if you configure
@@ -104,6 +104,7 @@ config IA64_GENERIC
 
 config IA64_DIG
        bool "DIG-compliant"
+       select SWIOTLB
 
 config IA64_HP_ZX1
        bool "HP-zx1/sx1000"
@@ -113,6 +114,7 @@ config IA64_HP_ZX1
 
 config IA64_HP_ZX1_SWIOTLB
        bool "HP-zx1/sx1000 with software I/O TLB"
+       select SWIOTLB
        help
          Build a kernel that runs on HP zx1 and sx1000 systems even when they
          have broken PCI devices which cannot DMA to full 32 bits.  Apart
@@ -131,6 +133,7 @@ config IA64_SGI_SN2
 
 config IA64_HP_SIM
        bool "Ski-simulator"
+       select SWIOTLB
 
 endchoice
 
index a5a5637507bea97f850b3fb2f03254534216f2e6..2153bcacbe6c9d29818608521293d08842594859 100644 (file)
@@ -192,3 +192,7 @@ EXPORT_SYMBOL(hwsw_unmap_sg);
 EXPORT_SYMBOL(hwsw_dma_supported);
 EXPORT_SYMBOL(hwsw_alloc_coherent);
 EXPORT_SYMBOL(hwsw_free_coherent);
+EXPORT_SYMBOL(hwsw_sync_single_for_cpu);
+EXPORT_SYMBOL(hwsw_sync_single_for_device);
+EXPORT_SYMBOL(hwsw_sync_sg_for_cpu);
+EXPORT_SYMBOL(hwsw_sync_sg_for_device);
index bc2f64d72244efdcf4a9c4a8fc9ba2a96149a5ac..9d92097ce96daaf5ccd2210eba88e44d53018ce6 100644 (file)
@@ -79,6 +79,7 @@ crash_save_this_cpu()
        final_note(buf);
 }
 
+#ifdef CONFIG_SMP
 static int
 kdump_wait_cpu_freeze(void)
 {
@@ -91,6 +92,7 @@ kdump_wait_cpu_freeze(void)
        }
        return 1;
 }
+#endif
 
 void
 machine_crash_shutdown(struct pt_regs *pt)
@@ -116,6 +118,11 @@ machine_crash_shutdown(struct pt_regs *pt)
 static void
 machine_kdump_on_init(void)
 {
+       if (!ia64_kimage) {
+               printk(KERN_NOTICE "machine_kdump_on_init(): "
+                               "kdump not configured\n");
+               return;
+       }
        local_irq_disable();
        kexec_disable_iosapic();
        machine_kexec(ia64_kimage);
@@ -132,11 +139,12 @@ kdump_cpu_freeze(struct unw_frame_info *info, void *arg)
        atomic_inc(&kdump_cpu_freezed);
        kdump_status[cpuid] = 1;
        mb();
-       if (cpuid == 0) {
-               for (;;)
-                       cpu_relax();
-       } else
+#ifdef CONFIG_HOTPLUG_CPU
+       if (cpuid != 0)
                ia64_jump_to_sal(&sal_boot_rendez_state[cpuid]);
+#endif
+       for (;;)
+               cpu_relax();
 }
 
 static int
index 83b8c91c1408f30c7186ecf3770babbe5bcd9e45..da60e90eeeb1493ee21ab75b130eb3d15732ae83 100644 (file)
@@ -9,7 +9,8 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 
-#include <linux/uaccess.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
 
 /**
  * copy_oldmem_page - copy one page from "oldmem"
index 0b25a7d4e1e4006f3de7f52edff67c56e5b0f4a0..6c03928544c233cb4b3e5c14537b56f9a7fe3898 100644 (file)
@@ -380,7 +380,7 @@ efi_get_pal_addr (void)
 #endif
                return __va(md->phys_addr);
        }
-       printk(KERN_WARNING "%s: no PAL-code memory-descriptor found",
+       printk(KERN_WARNING "%s: no PAL-code memory-descriptor found\n",
               __FUNCTION__);
        return NULL;
 }
index 15234ed3a3419f28dccd01209deb71767e45681f..e7873eeae448c15ec1e6ecb7718974e67bce8786 100644 (file)
@@ -1610,5 +1610,7 @@ sys_call_table:
        data8 sys_sync_file_range               // 1300
        data8 sys_tee
        data8 sys_vmsplice
+       data8 sys_ni_syscall                    // reserved for move_pages
+       data8 sys_getcpu
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
index 0fc5fb7865cfc40fd1664faf3a37abee6e4ee99a..d6aab40c64166ecdf6ae8c3529134e46ac4cd7a6 100644 (file)
@@ -925,6 +925,11 @@ iosapic_unregister_intr (unsigned int gsi)
                        /* Clear the interrupt controller descriptor */
                        idesc->chip = &no_irq_type;
 
+#ifdef CONFIG_SMP
+                       /* Clear affinity */
+                       cpus_setall(idesc->affinity);
+#endif
+
                        /* Clear the interrupt information */
                        memset(&iosapic_intr_info[vector], 0,
                               sizeof(struct iosapic_intr_info));
index e2ccc9f660c5730e1bbe77adc4f0cccafadbfdb7..4f0f3b8c1ee2b14cdd6b498fae39bb94fc818f18 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/kexec.h>
 #include <linux/cpu.h>
 #include <linux/irq.h>
+#include <linux/efi.h>
 #include <asm/mmu_context.h>
 #include <asm/setup.h>
 #include <asm/delay.h>
@@ -68,22 +69,10 @@ void machine_kexec_cleanup(struct kimage *image)
 {
 }
 
-void machine_shutdown(void)
-{
-       int cpu;
-
-       for_each_online_cpu(cpu) {
-               if (cpu != smp_processor_id())
-                       cpu_down(cpu);
-       }
-       kexec_disable_iosapic();
-}
-
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
  */
-extern void *efi_get_pal_addr(void);
 static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
 {
        struct kimage *image = arg;
@@ -93,6 +82,7 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
        unsigned long vector;
        int ii;
 
+       BUG_ON(!image);
        if (image->type == KEXEC_TYPE_CRASH) {
                crash_save_this_cpu();
                current->thread.ksp = (__u64)info->sw - 16;
@@ -131,6 +121,7 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg)
 
 void machine_kexec(struct kimage *image)
 {
+       BUG_ON(!image);
        unw_init_running(ia64_machine_kexec, image);
        for(;;);
 }
index 17685abaf49642659b1598f8d5474168c05bc19e..ae96d4176995e9dc84a5172c08393efa99cb8d20 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/ia32.h>
 #include <asm/irq.h>
 #include <asm/kdebug.h>
+#include <asm/kexec.h>
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/sal.h>
@@ -803,6 +804,21 @@ cpu_halt (void)
                ia64_pal_halt(min_power_state);
 }
 
+void machine_shutdown(void)
+{
+#ifdef CONFIG_HOTPLUG_CPU
+       int cpu;
+
+       for_each_online_cpu(cpu) {
+               if (cpu != smp_processor_id())
+                       cpu_down(cpu);
+       }
+#endif
+#ifdef CONFIG_KEXEC
+       kexec_disable_iosapic();
+#endif
+}
+
 void
 machine_restart (char *restart_cmd)
 {
index aa705e46b974d4d47aa4b9066bd2a017ec9b8c1b..3f8918782e0c992721a1758c1f83e2446f5261fe 100644 (file)
@@ -607,7 +607,7 @@ find_thread_for_addr (struct task_struct *child, unsigned long addr)
         */
        list_for_each_safe(this, next, &current->children) {
                p = list_entry(this, struct task_struct, sibling);
-               if (p->mm != mm)
+               if (p->tgid != child->tgid)
                        continue;
                if (thread_matches(p, addr)) {
                        child = p;
@@ -1405,6 +1405,7 @@ ptrace_disable (struct task_struct *child)
        struct ia64_psr *child_psr = ia64_psr(task_pt_regs(child));
 
        /* make sure the single step/taken-branch trap bits are not set: */
+       clear_tsk_thread_flag(child, TIF_SINGLESTEP);
        child_psr->ss = 0;
        child_psr->tb = 0;
 }
@@ -1525,6 +1526,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
                 * Make sure the single step/taken-branch trap bits
                 * are not set:
                 */
+               clear_tsk_thread_flag(child, TIF_SINGLESTEP);
                ia64_psr(pt)->ss = 0;
                ia64_psr(pt)->tb = 0;
 
@@ -1556,6 +1558,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
                        goto out_tsk;
 
                clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+               set_tsk_thread_flag(child, TIF_SINGLESTEP);
                if (request == PTRACE_SINGLESTEP) {
                        ia64_psr(pt)->ss = 1;
                } else {
@@ -1595,13 +1598,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data)
 }
 
 
-void
+static void
 syscall_trace (void)
 {
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
-       if (!(current->ptrace & PT_PTRACED))
-               return;
        /*
         * The 0x80 provides a way for the tracing parent to
         * distinguish between a syscall stop and SIGTRAP delivery.
@@ -1664,7 +1663,8 @@ syscall_trace_leave (long arg0, long arg1, long arg2, long arg3,
                audit_syscall_exit(success, result);
        }
 
-       if (test_thread_flag(TIF_SYSCALL_TRACE)
+       if ((test_thread_flag(TIF_SYSCALL_TRACE)
+           || test_thread_flag(TIF_SINGLESTEP))
            && (current->ptrace & PT_PTRACED))
                syscall_trace();
 }
index ad567b8d432e6552bea031db3fe5d55c8c174c54..83c2629e1c4c001cc56bae5fec820863dc9339fb 100644 (file)
@@ -569,34 +569,31 @@ show_cpuinfo (struct seq_file *m, void *v)
                { 1UL << 1, "spontaneous deferral"},
                { 1UL << 2, "16-byte atomic ops" }
        };
-       char features[128], *cp, sep;
+       char features[128], *cp, *sep;
        struct cpuinfo_ia64 *c = v;
        unsigned long mask;
        unsigned long proc_freq;
-       int i;
+       int i, size;
 
        mask = c->features;
 
        /* build the feature string: */
-       memcpy(features, " standard", 10);
+       memcpy(features, "standard", 9);
        cp = features;
-       sep = 0;
-       for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) {
+       size = sizeof(features);
+       sep = "";
+       for (i = 0; i < ARRAY_SIZE(feature_bits) && size > 1; ++i) {
                if (mask & feature_bits[i].mask) {
-                       if (sep)
-                               *cp++ = sep;
-                       sep = ',';
-                       *cp++ = ' ';
-                       strcpy(cp, feature_bits[i].feature_name);
-                       cp += strlen(feature_bits[i].feature_name);
+                       cp += snprintf(cp, size, "%s%s", sep,
+                                      feature_bits[i].feature_name),
+                       sep = ", ";
                        mask &= ~feature_bits[i].mask;
+                       size = sizeof(features) - (cp - features);
                }
        }
-       if (mask) {
-               /* print unknown features as a hex value: */
-               if (sep)
-                       *cp++ = sep;
-               sprintf(cp, " 0x%lx", mask);
+       if (mask && size > 1) {
+               /* print unknown features as a hex value */
+               snprintf(cp, size, "%s0x%lx", sep, mask);
        }
 
        proc_freq = cpufreq_quick_get(cpunum);
@@ -612,7 +609,7 @@ show_cpuinfo (struct seq_file *m, void *v)
                   "model name : %s\n"
                   "revision   : %u\n"
                   "archrev    : %u\n"
-                  "features   :%s\n"   /* don't change this---it _is_ right! */
+                  "features   : %s\n"
                   "cpu number : %lu\n"
                   "cpu regs   : %u\n"
                   "cpu MHz    : %lu.%06lu\n"
index d6083a0936f4e2e3ddd2c425e41ef0afc33ecb97..8f3d0066f4468cffbb980ce04e091ea48c4b6106 100644 (file)
@@ -157,6 +157,7 @@ SECTIONS
        }
 #endif
 
+  . = ALIGN(8);
    __con_initcall_start = .;
   .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET)
        { *(.con_initcall.init) }
index 1e79551231b91de2bdac6de77ef03b688c31434f..63e6d49c5813ed2bac5d027f0668a80080544a97 100644 (file)
@@ -30,47 +30,69 @@ static unsigned long max_gap;
 #endif
 
 /**
- * show_mem - display a memory statistics summary
+ * show_mem - give short summary of memory stats
  *
- * Just walks the pages in the system and describes where they're allocated.
+ * Shows a simple page count of reserved and used pages in the system.
+ * For discontig machines, it does this on a per-pgdat basis.
  */
-void
-show_mem (void)
+void show_mem(void)
 {
-       int i, total = 0, reserved = 0;
-       int shared = 0, cached = 0;
+       int i, total_reserved = 0;
+       int total_shared = 0, total_cached = 0;
+       unsigned long total_present = 0;
+       pg_data_t *pgdat;
 
        printk(KERN_INFO "Mem-info:\n");
        show_free_areas();
-
        printk(KERN_INFO "Free swap:       %6ldkB\n",
               nr_swap_pages<<(PAGE_SHIFT-10));
-       i = max_mapnr;
-       for (i = 0; i < max_mapnr; i++) {
-               if (!pfn_valid(i)) {
+       printk(KERN_INFO "Node memory in pages:\n");
+       for_each_online_pgdat(pgdat) {
+               unsigned long present;
+               unsigned long flags;
+               int shared = 0, cached = 0, reserved = 0;
+
+               pgdat_resize_lock(pgdat, &flags);
+               present = pgdat->node_present_pages;
+               for(i = 0; i < pgdat->node_spanned_pages; i++) {
+                       struct page *page;
+                       if (pfn_valid(pgdat->node_start_pfn + i))
+                               page = pfn_to_page(pgdat->node_start_pfn + i);
+                       else {
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-                       if (max_gap < LARGE_GAP)
-                               continue;
-                       i = vmemmap_find_next_valid_pfn(0, i) - 1;
+                               if (max_gap < LARGE_GAP)
+                                       continue;
 #endif
-                       continue;
+                               i = vmemmap_find_next_valid_pfn(pgdat->node_id,
+                                        i) - 1;
+                               continue;
+                       }
+                       if (PageReserved(page))
+                               reserved++;
+                       else if (PageSwapCache(page))
+                               cached++;
+                       else if (page_count(page))
+                               shared += page_count(page)-1;
                }
-               total++;
-               if (PageReserved(mem_map+i))
-                       reserved++;
-               else if (PageSwapCache(mem_map+i))
-                       cached++;
-               else if (page_count(mem_map + i))
-                       shared += page_count(mem_map + i) - 1;
+               pgdat_resize_unlock(pgdat, &flags);
+               total_present += present;
+               total_reserved += reserved;
+               total_cached += cached;
+               total_shared += shared;
+               printk(KERN_INFO "Node %4d:  RAM: %11ld, rsvd: %8d, "
+                      "shrd: %10d, swpd: %10d\n", pgdat->node_id,
+                      present, reserved, shared, cached);
        }
-       printk(KERN_INFO "%d pages of RAM\n", total);
-       printk(KERN_INFO "%d reserved pages\n", reserved);
-       printk(KERN_INFO "%d pages shared\n", shared);
-       printk(KERN_INFO "%d pages swap cached\n", cached);
-       printk(KERN_INFO "%ld pages in page table cache\n",
+       printk(KERN_INFO "%ld pages of RAM\n", total_present);
+       printk(KERN_INFO "%d reserved pages\n", total_reserved);
+       printk(KERN_INFO "%d pages shared\n", total_shared);
+       printk(KERN_INFO "%d pages swap cached\n", total_cached);
+       printk(KERN_INFO "Total of %ld pages in page table cache\n",
               pgtable_quicklist_total_size());
+       printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages());
 }
 
+
 /* physical address where the bootmem map is located */
 unsigned long bootmap_start;
 
@@ -177,7 +199,7 @@ find_memory (void)
 
 #ifdef CONFIG_CRASH_DUMP
        /* If we are doing a crash dump, we still need to know the real mem
-        * size before original memory map is reset. */
+        * size before original memory map is reset. */
        saved_max_pfn = max_pfn;
 #endif
 }
index 96722cb1b49ddbc296951fa1007b2f418d910dea..6eae596c509d5cc5c17a5ebc5b5702f4e6d6bf01 100644 (file)
@@ -412,37 +412,6 @@ static void __init memory_less_nodes(void)
        return;
 }
 
-#ifdef CONFIG_SPARSEMEM
-/**
- * register_sparse_mem - notify SPARSEMEM that this memory range exists.
- * @start: physical start of range
- * @end: physical end of range
- * @arg: unused
- *
- * Simply calls SPARSEMEM to register memory section(s).
- */
-static int __init register_sparse_mem(unsigned long start, unsigned long end,
-       void *arg)
-{
-       int nid;
-
-       start = __pa(start) >> PAGE_SHIFT;
-       end = __pa(end) >> PAGE_SHIFT;
-       nid = early_pfn_to_nid(start);
-       memory_present(nid, start, end);
-
-       return 0;
-}
-
-static void __init arch_sparse_init(void)
-{
-       efi_memmap_walk(register_sparse_mem, NULL);
-       sparse_init();
-}
-#else
-#define arch_sparse_init() do {} while (0)
-#endif
-
 /**
  * find_memory - walk the EFI memory map and setup the bootmem allocator
  *
@@ -473,6 +442,9 @@ void __init find_memory(void)
                        node_clear(node, memory_less_mask);
                        mem_data[node].min_pfn = ~0UL;
                }
+
+       efi_memmap_walk(register_active_ranges, NULL);
+
        /*
         * Initialize the boot memory maps in reverse order since that's
         * what the bootmem allocator expects
@@ -506,6 +478,12 @@ void __init find_memory(void)
        max_pfn = max_low_pfn;
 
        find_initrd();
+
+#ifdef CONFIG_CRASH_DUMP
+       /* If we are doing a crash dump, we still need to know the real mem
+        * size before original memory map is reset. */
+        saved_max_pfn = max_pfn;
+#endif
 }
 
 #ifdef CONFIG_SMP
@@ -654,7 +632,6 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n
 {
        unsigned long end = start + len;
 
-       add_active_range(node, start >> PAGE_SHIFT, end >> PAGE_SHIFT);
        mem_data[node].num_physpages += len >> PAGE_SHIFT;
        if (start <= __pa(MAX_DMA_ADDRESS))
                mem_data[node].num_dma_physpages +=
@@ -686,10 +663,11 @@ void __init paging_init(void)
 
        max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
-       arch_sparse_init();
-
        efi_memmap_walk(filter_rsvd_memory, count_node_pages);
 
+       sparse_memory_present_with_active_regions(MAX_NUMNODES);
+       sparse_init();
+
 #ifdef CONFIG_VIRTUAL_MEM_MAP
        vmalloc_end -= PAGE_ALIGN(ALIGN(max_low_pfn, MAX_ORDER_NR_PAGES) *
                sizeof(struct page));
index 1373fae7657fe4bf5a17e6b4e449bcddad67906f..faaca21a3718c5e7b5b82ed7a5b04fbc7c586a8e 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/swap.h>
 #include <linux/proc_fs.h>
 #include <linux/bitops.h>
+#include <linux/kexec.h>
 
 #include <asm/a.out.h>
 #include <asm/dma.h>
@@ -128,6 +129,25 @@ lazy_mmu_prot_update (pte_t pte)
        set_bit(PG_arch_1, &page->flags);       /* mark page as clean */
 }
 
+/*
+ * Since DMA is i-cache coherent, any (complete) pages that were written via
+ * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
+ * flush them when they get mapped into an executable vm-area.
+ */
+void
+dma_mark_clean(void *addr, size_t size)
+{
+       unsigned long pg_addr, end;
+
+       pg_addr = PAGE_ALIGN((unsigned long) addr);
+       end = (unsigned long) addr + size;
+       while (pg_addr + PAGE_SIZE <= end) {
+               struct page *page = virt_to_page(pg_addr);
+               set_bit(PG_arch_1, &page->flags);
+               pg_addr += PAGE_SIZE;
+       }
+}
+
 inline void
 ia64_set_rbs_bot (void)
 {
@@ -595,13 +615,27 @@ find_largest_hole (u64 start, u64 end, void *arg)
        return 0;
 }
 
+#endif /* CONFIG_VIRTUAL_MEM_MAP */
+
 int __init
 register_active_ranges(u64 start, u64 end, void *arg)
 {
-       add_active_range(0, __pa(start) >> PAGE_SHIFT, __pa(end) >> PAGE_SHIFT);
+       int nid = paddr_to_nid(__pa(start));
+
+       if (nid < 0)
+               nid = 0;
+#ifdef CONFIG_KEXEC
+       if (start > crashk_res.start && start < crashk_res.end)
+               start = crashk_res.end;
+       if (end > crashk_res.start && end < crashk_res.end)
+               end = crashk_res.start;
+#endif
+
+       if (start < end)
+               add_active_range(nid, __pa(start) >> PAGE_SHIFT,
+                       __pa(end) >> PAGE_SHIFT);
        return 0;
 }
-#endif /* CONFIG_VIRTUAL_MEM_MAP */
 
 static int __init
 count_reserved_pages (u64 start, u64 end, void *arg)
index abca6bd7962f7a14d30adbeb79d4c7b71f61e34b..fcf7f93c4b615f83bdd1cd0296a74515e11f595b 100644 (file)
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000,2002-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000,2002-2007 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/types.h>
@@ -38,12 +38,20 @@ static irqreturn_t hub_eint_handler(int irq, void *arg)
                        (u64) nasid, 0, 0, 0, 0, 0, 0);
 
                if ((int)ret_stuff.v0)
-                       panic("hubii_eint_handler(): Fatal TIO Error");
+                       panic("%s: Fatal %s Error", __FUNCTION__,
+                               ((nasid & 1) ? "TIO" : "HUBII"));
 
                if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
                        (void)hubiio_crb_error_handler(hubdev_info);
-       } else 
-               bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid)));
+       } else
+               if (nasid & 1) {        /* TIO errors */
+                       SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
+                               (u64) nasid, 0, 0, 0, 0, 0, 0);
+
+                       if ((int)ret_stuff.v0)
+                               panic("%s: Fatal TIO Error", __FUNCTION__);
+               } else
+                       bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid)));
 
        return IRQ_HANDLED;
 }
index bbd386f572d97a6ed6cc8413f50d5e09ac019382..44a0224c32ddbe39d30c3134b4d41766e95d4d0b 100644 (file)
@@ -575,6 +575,7 @@ config SGI_IP27
        select DMA_IP27
        select EARLY_PRINTK
        select HW_HAS_PCI
+       select NR_CPUS_DEFAULT_64
        select PCI_DOMAINS
        select SYS_HAS_CPU_R10000
        select SYS_SUPPORTS_64BIT_KERNEL
@@ -612,6 +613,7 @@ config SIBYTE_BIGSUR
        bool "Sibyte BCM91480B-BigSur"
        select BOOT_ELF32
        select DMA_COHERENT
+       select NR_CPUS_DEFAULT_4
        select PCI_DOMAINS
        select SIBYTE_BCM1x80
        select SWAP_IO_SPACE
@@ -623,6 +625,7 @@ config SIBYTE_SWARM
        bool "Sibyte BCM91250A-SWARM"
        select BOOT_ELF32
        select DMA_COHERENT
+       select NR_CPUS_DEFAULT_2
        select SIBYTE_SB1250
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_SB1
@@ -635,6 +638,7 @@ config SIBYTE_SENTOSA
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
+       select NR_CPUS_DEFAULT_2
        select SIBYTE_SB1250
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_SB1
@@ -668,6 +672,7 @@ config SIBYTE_PTSWARM
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
+       select NR_CPUS_DEFAULT_2
        select SIBYTE_SB1250
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_SB1
@@ -680,6 +685,7 @@ config SIBYTE_LITTLESUR
        depends on EXPERIMENTAL
        select BOOT_ELF32
        select DMA_COHERENT
+       select NR_CPUS_DEFAULT_2
        select SIBYTE_SB1250
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_SB1
@@ -790,23 +796,6 @@ config TOSHIBA_RBTX4938
 
 endchoice
 
-config KEXEC
-       bool "Kexec system call (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-       help
-         kexec is a system call that implements the ability to shutdown your
-         current kernel, and to start another kernel.  It is like a reboot
-         but it is indepedent of the system firmware.   And like a reboot
-         you can start any kernel with it, not just Linux.
-
-         The name comes from the similiarity to the exec system call.
-
-         It is an ongoing process to be certain the hardware in a machine
-         is properly shutdown, so do not be surprised if this code does not
-         initially work for you.  It may help to enable device hotplugging
-         support.  As of this writing the exact hardware interface is
-         strongly in flux, so no good recommendation can be made.
-
 source "arch/mips/ddb5xxx/Kconfig"
 source "arch/mips/gt64120/ev64120/Kconfig"
 source "arch/mips/jazz/Kconfig"
@@ -1541,6 +1530,8 @@ config MIPS_MT_SMTC
        select CPU_MIPSR2_IRQ_VI
        select CPU_MIPSR2_SRS
        select MIPS_MT
+       select NR_CPUS_DEFAULT_2
+       select NR_CPUS_DEFAULT_8
        select SMP
        select SYS_SUPPORTS_SMP
        help
@@ -1756,13 +1747,34 @@ config SMP
 config SYS_SUPPORTS_SMP
        bool
 
+config NR_CPUS_DEFAULT_2
+       bool
+
+config NR_CPUS_DEFAULT_4
+       bool
+
+config NR_CPUS_DEFAULT_8
+       bool
+
+config NR_CPUS_DEFAULT_16
+       bool
+
+config NR_CPUS_DEFAULT_32
+       bool
+
+config NR_CPUS_DEFAULT_64
+       bool
+
 config NR_CPUS
        int "Maximum number of CPUs (2-64)"
        range 2 64
        depends on SMP
-       default "64" if SGI_IP27
-       default "2"
-       default "8" if MIPS_MT_SMTC
+       default "2" if NR_CPUS_DEFAULT_2
+       default "4" if NR_CPUS_DEFAULT_4
+       default "8" if NR_CPUS_DEFAULT_8
+       default "16" if NR_CPUS_DEFAULT_16
+       default "32" if NR_CPUS_DEFAULT_32
+       default "64" if NR_CPUS_DEFAULT_64
        help
          This allows you to specify the maximum number of CPUs which this
          kernel will support.  The maximum supported value is 32 for 32-bit
@@ -1859,6 +1871,40 @@ config MIPS_INSANE_LARGE
          This will result in additional memory usage, so it is not
          recommended for normal users.
 
+config KEXEC
+       bool "Kexec system call (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       help
+         kexec is a system call that implements the ability to shutdown your
+         current kernel, and to start another kernel.  It is like a reboot
+         but it is indepedent of the system firmware.   And like a reboot
+         you can start any kernel with it, not just Linux.
+
+         The name comes from the similiarity to the exec system call.
+
+         It is an ongoing process to be certain the hardware in a machine
+         is properly shutdown, so do not be surprised if this code does not
+         initially work for you.  It may help to enable device hotplugging
+         support.  As of this writing the exact hardware interface is
+         strongly in flux, so no good recommendation can be made.
+
+config SECCOMP
+       bool "Enable seccomp to safely compute untrusted bytecode"
+       depends on PROC_FS && BROKEN
+       default y
+       help
+         This kernel feature is useful for number crunching applications
+         that may need to compute untrusted bytecode during their
+         execution. By using pipes or other transports made available to
+         the process as file descriptors supporting the read/write
+         syscalls, it's possible to isolate those applications in
+         their own address space using seccomp. Once seccomp is
+         enabled via /proc/<pid>/seccomp, it cannot be disabled
+         and the task is only allowed to execute a few safe syscalls
+         defined by each seccomp mode.
+
+         If unsure, say Y. Only embedded should say N here.
+
 endmenu
 
 config RWSEM_GENERIC_SPINLOCK
@@ -2025,23 +2071,6 @@ config BINFMT_ELF32
        bool
        default y if MIPS32_O32 || MIPS32_N32
 
-config SECCOMP
-       bool "Enable seccomp to safely compute untrusted bytecode"
-       depends on PROC_FS && BROKEN
-       default y
-       help
-         This kernel feature is useful for number crunching applications
-         that may need to compute untrusted bytecode during their
-         execution. By using pipes or other transports made available to
-         the process as file descriptors supporting the read/write
-         syscalls, it's possible to isolate those applications in
-         their own address space using seccomp. Once seccomp is
-         enabled via /proc/<pid>/seccomp, it cannot be disabled
-         and the task is only allowed to execute a few safe syscalls
-         defined by each seccomp mode.
-
-         If unsure, say Y. Only embedded should say N here.
-
 config PM
        bool "Power Management support (EXPERIMENTAL)"
        depends on EXPERIMENTAL && SOC_AU1X00
index 5d6afb52d904aecd6b618c86f42be901897cb7b3..9351f1c04a9d7144d0a024a86887d46ffea87d08 100644 (file)
@@ -22,10 +22,10 @@ config CMDLINE
        string "Default kernel command string"
        default ""
        help
-          On some platforms, there is currently no way for the boot loader to
-          pass arguments to the kernel. For these platforms, you can supply
-          some command-line options at build time by entering them here.  In
-          other cases you can specify kernel args so that you don't have
+         On some platforms, there is currently no way for the boot loader to
+         pass arguments to the kernel. For these platforms, you can supply
+         some command-line options at build time by entering them here.  In
+         other cases you can specify kernel args so that you don't have
          to set them up in board prom initialization routines.
 
 config DEBUG_STACK_USAGE
index 3ba7c47f9f23b1b9c4da4efcd31937ee0fcb39a7..4b907369b0f969d06d863e4cf0f8282fa656ca5d 100644 (file)
@@ -77,7 +77,7 @@ static struct smatch * __init string_to_mach(const char *s)
 {
        int i;
 
-       for (i = 0; i < (sizeof(mach_table) / sizeof (mach_table[0])); i++) {
+       for (i = 0; i < ARRAY_SIZE(mach_table); i++) {
                if (!strcmp(s, mach_table[i].arcname))
                        return &mach_table[i];
        }
index 8a9ef58cc399313b2b46125cf0b207cc4c9ce2ab..456cb81a32d9c88edb5d9abba1138f37cccb30aa 100644 (file)
@@ -141,30 +141,20 @@ void __init prom_meminit(void)
        }
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       unsigned long freed = 0;
        unsigned long addr;
        int i;
 
        if (prom_flags & PROM_FLAG_DONT_FREE_TEMP)
-               return 0;
+               return;
 
        for (i = 0; i < boot_mem_map.nr_map; i++) {
                if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
                        continue;
 
                addr = boot_mem_map.map[i].addr;
-               while (addr < boot_mem_map.map[i].addr
-                             + boot_mem_map.map[i].size) {
-                       ClearPageReserved(virt_to_page(__va(addr)));
-                       init_page_count(virt_to_page(__va(addr)));
-                       free_page((unsigned long)__va(addr));
-                       addr += PAGE_SIZE;
-                       freed += PAGE_SIZE;
-               }
+               free_init_pages("prom memory",
+                               addr, addr + boot_mem_map.map[i].size);
        }
-       printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10);
-
-       return freed;
 }
index 9cf7b6715836c914144955a2de1ec2b38f39e81d..ea6e99fbe2f7210826728c45bd1ae750f0fbaa7f 100644 (file)
@@ -233,7 +233,7 @@ void restore_local_and_enable(int controller, unsigned long mask)
 
 
 static struct irq_chip rise_edge_irq_type = {
-       .typename = "Au1000 Rise Edge",
+       .name = "Au1000 Rise Edge",
        .ack = mask_and_ack_rise_edge_irq,
        .mask = local_disable_irq,
        .mask_ack = mask_and_ack_rise_edge_irq,
@@ -242,7 +242,7 @@ static struct irq_chip rise_edge_irq_type = {
 };
 
 static struct irq_chip fall_edge_irq_type = {
-       .typename = "Au1000 Fall Edge",
+       .name = "Au1000 Fall Edge",
        .ack = mask_and_ack_fall_edge_irq,
        .mask = local_disable_irq,
        .mask_ack = mask_and_ack_fall_edge_irq,
@@ -251,7 +251,7 @@ static struct irq_chip fall_edge_irq_type = {
 };
 
 static struct irq_chip either_edge_irq_type = {
-       .typename = "Au1000 Rise or Fall Edge",
+       .name = "Au1000 Rise or Fall Edge",
        .ack = mask_and_ack_either_edge_irq,
        .mask = local_disable_irq,
        .mask_ack = mask_and_ack_either_edge_irq,
@@ -260,7 +260,7 @@ static struct irq_chip either_edge_irq_type = {
 };
 
 static struct irq_chip level_irq_type = {
-       .typename = "Au1000 Level",
+       .name = "Au1000 Level",
        .ack = mask_and_ack_level_irq,
        .mask = local_disable_irq,
        .mask_ack = mask_and_ack_level_irq,
index 9f8ce08e173b70700fd1367169666077008fb0f4..6c25e6c09f7835ed4c3183b316e157d86d2db174 100644 (file)
@@ -76,13 +76,17 @@ static int __init au1x_pci_setup(void)
        }
 
 #ifdef CONFIG_DMA_NONCOHERENT
-       /*
-         *  Set the NC bit in controller for Au1500 pre-AC silicon
-        */
-       u32 prid = read_c0_prid();
-       if ( (prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
-              au_writel( 1<<16 | au_readl(Au1500_PCI_CFG), Au1500_PCI_CFG);
-              printk("Non-coherent PCI accesses enabled\n");
+       {
+               /*
+                *  Set the NC bit in controller for Au1500 pre-AC silicon
+                */
+               u32 prid = read_c0_prid();
+
+               if ((prid & 0xFF000000) == 0x01000000 && prid < 0x01030202) {
+                      au_writel((1 << 16) | au_readl(Au1500_PCI_CFG),
+                                Au1500_PCI_CFG);
+                      printk("Non-coherent PCI accesses enabled\n");
+               }
        }
 #endif
 
index 6fce60af005dc7be1704d660d6d4ecc1fdcacd47..a8637cdb5b4b076a580e98ead98599e25bfa1650 100644 (file)
@@ -149,9 +149,8 @@ int get_ethernet_addr(char *ethernet_addr)
        return 0;
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 EXPORT_SYMBOL(prom_getcmdline);
index 919172db560cfa4d779e19fec1ae93b97aa80276..13fe187f35d67542a1bfa93acf4544d949ee7261 100644 (file)
@@ -141,17 +141,20 @@ void __init plat_mem_setup(void)
 /* This routine should be valid for all Au1x based boards */
 phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size)
 {
-       u32 start, end;
-
        /* Don't fixup 36 bit addresses */
-       if ((phys_addr >> 32) != 0) return phys_addr;
+       if ((phys_addr >> 32) != 0)
+               return phys_addr;
 
 #ifdef CONFIG_PCI
-       start = (u32)Au1500_PCI_MEM_START;
-       end = (u32)Au1500_PCI_MEM_END;
-       /* check for pci memory window */
-       if ((phys_addr >= start) && ((phys_addr + size) < end)) {
-               return (phys_t)((phys_addr - start) + Au1500_PCI_MEM_START);
+       {
+               u32 start, end;
+
+               start = (u32)Au1500_PCI_MEM_START;
+               end = (u32)Au1500_PCI_MEM_END;
+               /* check for pci memory window */
+               if ((phys_addr >= start) && ((phys_addr + size) < end))
+                       return (phys_t)
+                              ((phys_addr - start) + Au1500_PCI_MEM_START);
        }
 #endif
 
index 2d1533f116c0c020f57a4de59c952b6167f3545c..6bc1f8e1b608175b431f6927d47aa42558d8f1cc 100644 (file)
@@ -47,8 +47,7 @@ void board_reset (void)
 
 void __init board_setup(void)
 {
-       u32 pin_func;
-       u32 sys_freqctrl, sys_clksrc;
+       volatile void __iomem * base = (volatile void __iomem *) 0xac000000UL;
 
        // set AUX clock to 12MHz * 8 = 96 MHz
        au_writel(8, SYS_AUXPLL);
@@ -56,58 +55,62 @@ void __init board_setup(void)
        udelay(100);
 
 #ifdef CONFIG_USB_OHCI
-       // configure pins GPIO[14:9] as GPIO
-       pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80);
-
-       /* zero and disable FREQ2 */
-       sys_freqctrl = au_readl(SYS_FREQCTRL0);
-       sys_freqctrl &= ~0xFFF00000;
-       au_writel(sys_freqctrl, SYS_FREQCTRL0);
-
-       /* zero and disable USBH/USBD/IrDA clock */
-       sys_clksrc = au_readl(SYS_CLKSRC);
-       sys_clksrc &= ~0x0000001F;
-       au_writel(sys_clksrc, SYS_CLKSRC);
-
-       sys_freqctrl = au_readl(SYS_FREQCTRL0);
-       sys_freqctrl &= ~0xFFF00000;
-
-       sys_clksrc = au_readl(SYS_CLKSRC);
-       sys_clksrc &= ~0x0000001F;
-
-       // FREQ2 = aux/2 = 48 MHz
-       sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
-       au_writel(sys_freqctrl, SYS_FREQCTRL0);
-
-       /*
-        * Route 48MHz FREQ2 into USBH/USBD/IrDA
-        */
-       sys_clksrc |= ((4<<2) | (0<<1) | 0 );
-       au_writel(sys_clksrc, SYS_CLKSRC);
-
-       /* setup the static bus controller */
-       au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
-       au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
-       au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
-
-       // get USB Functionality pin state (device vs host drive pins)
-       pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
-       // 2nd USB port is USB host
-       pin_func |= 0x8000;
-       au_writel(pin_func, SYS_PINFUNC);
+       {
+               u32 pin_func, sys_freqctrl, sys_clksrc;
+
+               // configure pins GPIO[14:9] as GPIO
+               pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80);
+
+               /* zero and disable FREQ2 */
+               sys_freqctrl = au_readl(SYS_FREQCTRL0);
+               sys_freqctrl &= ~0xFFF00000;
+               au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+               /* zero and disable USBH/USBD/IrDA clock */
+               sys_clksrc = au_readl(SYS_CLKSRC);
+               sys_clksrc &= ~0x0000001F;
+               au_writel(sys_clksrc, SYS_CLKSRC);
+
+               sys_freqctrl = au_readl(SYS_FREQCTRL0);
+               sys_freqctrl &= ~0xFFF00000;
+
+               sys_clksrc = au_readl(SYS_CLKSRC);
+               sys_clksrc &= ~0x0000001F;
+
+               // FREQ2 = aux/2 = 48 MHz
+               sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20));
+               au_writel(sys_freqctrl, SYS_FREQCTRL0);
+
+               /*
+                * Route 48MHz FREQ2 into USBH/USBD/IrDA
+                */
+               sys_clksrc |= ((4<<2) | (0<<1) | 0 );
+               au_writel(sys_clksrc, SYS_CLKSRC);
+
+               /* setup the static bus controller */
+               au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
+               au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
+               au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */
+
+               // get USB Functionality pin state (device vs host drive pins)
+               pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+               // 2nd USB port is USB host
+               pin_func |= 0x8000;
+               au_writel(pin_func, SYS_PINFUNC);
+       }
 #endif // defined (CONFIG_USB_OHCI)
 
        /* Enable sys bus clock divider when IDLE state or no bus activity. */
        au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
 
        // Enable the RTC if not already enabled
-       if (!(readb(0xac000028) & 0x20)) {
-               writeb(readb(0xac000028) | 0x20, 0xac000028);
+       if (!(readb(base + 0x28) & 0x20)) {
+               writeb(readb(base + 0x28) | 0x20, base + 0x28);
                au_sync();
        }
        // Put the clock in BCD mode
-       if (readb(0xac00002C) & 0x4) { /* reg B */
-               writeb(readb(0xac00002c) & ~0x4, 0xac00002c);
+       if (readb(base + 0x2C) & 0x4) { /* reg B */
+               writeb(readb(base + 0x2c) & ~0x4, base + 0x2c);
                au_sync();
        }
 }
index 91983ba407c4731fd64c40358a1b56c29bdb07d3..b73b2d18bf56885d8f84278fa28330c3502040a7 100644 (file)
@@ -137,33 +137,20 @@ static void pb1200_shutdown_irq( unsigned int irq_nr )
        return;
 }
 
-static inline void pb1200_mask_and_ack_irq(unsigned int irq_nr)
-{
-       pb1200_disable_irq( irq_nr );
-}
-
-static void pb1200_end_irq(unsigned int irq_nr)
-{
-       if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
-               pb1200_enable_irq(irq_nr);
-       }
-}
-
 static struct irq_chip external_irq_type =
 {
 #ifdef CONFIG_MIPS_PB1200
-       "Pb1200 Ext",
+       .name = "Pb1200 Ext",
 #endif
 #ifdef CONFIG_MIPS_DB1200
-       "Db1200 Ext",
+       .name = "Db1200 Ext",
 #endif
-       pb1200_startup_irq,
-       pb1200_shutdown_irq,
-       pb1200_enable_irq,
-       pb1200_disable_irq,
-       pb1200_mask_and_ack_irq,
-       pb1200_end_irq,
-       NULL
+       .startup  = pb1200_startup_irq,
+       .shutdown = pb1200_shutdown_irq,
+       .ack      = pb1200_disable_irq,
+       .mask     = pb1200_disable_irq,
+       .mask_ack = pb1200_disable_irq,
+       .unmask   = pb1200_enable_irq,
 };
 
 void _board_init_irq(void)
@@ -172,7 +159,8 @@ void _board_init_irq(void)
 
        for (irq_nr = PB1200_INT_BEGIN; irq_nr <= PB1200_INT_END; irq_nr++)
        {
-               irq_desc[irq_nr].chip = &external_irq_type;
+               set_irq_chip_and_handler(irq_nr, &external_irq_type,
+                                        handle_level_irq);
                pb1200_disable_irq(irq_nr);
        }
 
index 2e2061a286c5664f45649c6def0d8fc101322583..1ecab6350421cdeef9101185aac4ce0a3e26179f 100644 (file)
@@ -47,9 +47,9 @@ extern asmlinkage void excite_handle_int(void);
  */
 void __init arch_init_irq(void)
 {
-       mips_cpu_irq_init(0);
-       rm7k_cpu_irq_init(8);
-       rm9k_cpu_irq_init(12);
+       mips_cpu_irq_init();
+       rm7k_cpu_irq_init();
+       rm9k_cpu_irq_init();
 
 #ifdef CONFIG_KGDB
        excite_kgdb_init();
index 4c46f0e737832c2e7cecf5117c95d50b228cecc4..fe93b846923b85fd873953aefbe62bc9a6cf7d85 100644 (file)
@@ -104,7 +104,7 @@ void __init arch_init_irq(void)
        GT_WRITE(GT_INTRMASK_OFS, 0);
 
        init_i8259_irqs();                              /*  0 ... 15 */
-       mips_cpu_irq_init(COBALT_CPU_IRQ);              /* 16 ... 23 */
+       mips_cpu_irq_init();            /* 16 ... 23 */
 
        /*
         * Mask all cpu interrupts
index e8f0f20b852dec3eb7215530bd9ea483161019a9..a4b69b543bd903984433089474d3557e983bb218 100644 (file)
@@ -204,8 +204,7 @@ void __init prom_init(void)
        add_memory_region(0x0, memsz, BOOT_MEM_RAM);
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
        /* Nothing to do! */
-       return 0;
 }
index efef0f57ce1e56d789c03ec986f72db966b2fb7f..54a857b5e3baa5f7151b64714ca53fec8f07b218 100644 (file)
@@ -59,9 +59,8 @@ void __init prom_init(void)
 #endif
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 #if defined(CONFIG_DDB5477)
index a8bd2e66705ce3fda7885426903ee4a4da98d2e6..2b23234a5b95ec4a76db0f0b7a56ca804f265b5e 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/ptrace.h>
 
 #include <asm/i8259.h>
+#include <asm/irq_cpu.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
 #include <asm/debug.h>
@@ -73,7 +74,6 @@ set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
 }
 
 extern void vrc5477_irq_init(u32 base);
-extern void mips_cpu_irq_init(u32 base);
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
 void __init arch_init_irq(void)
@@ -125,7 +125,7 @@ void __init arch_init_irq(void)
 
        /* init all controllers */
        init_i8259_irqs();
-       mips_cpu_irq_init(CPU_IRQ_BASE);
+       mips_cpu_irq_init();
        vrc5477_irq_init(VRC5477_IRQ_BASE);
 
 
@@ -146,8 +146,7 @@ u8 i8259_interrupt_ack(void)
        irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
        ddb_out32(DDB_PCIINIT10, reg);
 
-       /* i8259.c set the base vector to be 0x0 */
-       return irq + I8259_IRQ_BASE;
+       return irq;
 }
 /*
  * the first level int-handler will jump here if it is a vrc5477 irq
@@ -177,7 +176,7 @@ static void vrc5477_irq_dispatch(void)
                /* check for i8259 interrupts */
                if (intStatus & (1 << VRC5477_I8259_CASCADE)) {
                        int i8259_irq = i8259_interrupt_ack();
-                       do_IRQ(I8259_IRQ_BASE + i8259_irq);
+                       do_IRQ(i8259_irq);
                        return;
                }
        }
index 96249aa5df5d2229d6675d1bdfefe629e5e31cfe..98c3b15eb369131d9419aafe1187d84d65b7a1c1 100644 (file)
@@ -82,7 +82,7 @@ vrc5477_irq_end(unsigned int irq)
 }
 
 struct irq_chip vrc5477_irq_controller = {
-       .typename = "vrc5477_irq",
+       .name = "vrc5477_irq",
        .ack = vrc5477_irq_ack,
        .mask = vrc5477_irq_disable,
        .mask_ack = vrc5477_irq_ack,
index 4c7cb4048d358126b84b81d509fe7a8d9ec94903..3acb133668dc12f5731aab6b611c8756a6fa89a1 100644 (file)
@@ -62,7 +62,7 @@ static inline void end_ioasic_irq(unsigned int irq)
 }
 
 static struct irq_chip ioasic_irq_type = {
-       .typename = "IO-ASIC",
+       .name = "IO-ASIC",
        .ack = ack_ioasic_irq,
        .mask = mask_ioasic_irq,
        .mask_ack = ack_ioasic_irq,
@@ -84,7 +84,7 @@ static inline void end_ioasic_dma_irq(unsigned int irq)
 }
 
 static struct irq_chip ioasic_dma_irq_type = {
-       .typename = "IO-ASIC-DMA",
+       .name = "IO-ASIC-DMA",
        .ack = ack_ioasic_dma_irq,
        .mask = mask_ioasic_dma_irq,
        .mask_ack = ack_ioasic_dma_irq,
index 916e46b8ccd8489cb27b74bcfc31da537d6b102f..02439dc0ba83136209b0945a1cb77d39601e244b 100644 (file)
@@ -58,7 +58,7 @@ static void ack_kn02_irq(unsigned int irq)
 }
 
 static struct irq_chip kn02_irq_type = {
-       .typename = "KN02-CSR",
+       .name = "KN02-CSR",
        .ack = ack_kn02_irq,
        .mask = mask_kn02_irq,
        .mask_ack = ack_kn02_irq,
index 3aa01d268f2d4f45398bd1ece332c0ecfa4d39ce..5a557e268f78440273ef6174c4b54ca40c104807 100644 (file)
@@ -92,9 +92,9 @@ void __init prom_meminit(u32 magic)
                rex_setup_memory_region();
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       unsigned long addr, end;
+       unsigned long end;
 
        /*
         * Free everything below the kernel itself but leave
@@ -114,16 +114,5 @@ unsigned long __init prom_free_prom_memory(void)
 #endif
                end = __pa(&_text);
 
-       addr = PAGE_SIZE;
-       while (addr < end) {
-               ClearPageReserved(virt_to_page(__va(addr)));
-               init_page_count(virt_to_page(__va(addr)));
-               free_page((unsigned long)__va(addr));
-               addr += PAGE_SIZE;
-       }
-
-       printk("Freeing unused PROM memory: %ldkb freed\n",
-              (end - PAGE_SIZE) >> 10);
-
-       return end - PAGE_SIZE;
+       free_init_pages("unused PROM memory", PAGE_SIZE, end);
 }
index d34032ac492a1ac24a9954f2ab789780b2bb8a04..1058e2f409bb9ec6a3fed658103affd4d5b338d1 100644 (file)
@@ -234,7 +234,7 @@ static void __init dec_init_kn01(void)
        memcpy(&cpu_mask_nr_tbl, &kn01_cpu_mask_nr_tbl,
                sizeof(kn01_cpu_mask_nr_tbl));
 
-       mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+       mips_cpu_irq_init();
 
 }                              /* dec_init_kn01 */
 
@@ -309,7 +309,7 @@ static void __init dec_init_kn230(void)
        memcpy(&cpu_mask_nr_tbl, &kn230_cpu_mask_nr_tbl,
                sizeof(kn230_cpu_mask_nr_tbl));
 
-       mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+       mips_cpu_irq_init();
 
 }                              /* dec_init_kn230 */
 
@@ -403,7 +403,7 @@ static void __init dec_init_kn02(void)
        memcpy(&asic_mask_nr_tbl, &kn02_asic_mask_nr_tbl,
                sizeof(kn02_asic_mask_nr_tbl));
 
-       mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+       mips_cpu_irq_init();
        init_kn02_irqs(KN02_IRQ_BASE);
 
 }                              /* dec_init_kn02 */
@@ -504,7 +504,7 @@ static void __init dec_init_kn02ba(void)
        memcpy(&asic_mask_nr_tbl, &kn02ba_asic_mask_nr_tbl,
                sizeof(kn02ba_asic_mask_nr_tbl));
 
-       mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+       mips_cpu_irq_init();
        init_ioasic_irqs(IO_IRQ_BASE);
 
 }                              /* dec_init_kn02ba */
@@ -601,7 +601,7 @@ static void __init dec_init_kn02ca(void)
        memcpy(&asic_mask_nr_tbl, &kn02ca_asic_mask_nr_tbl,
                sizeof(kn02ca_asic_mask_nr_tbl));
 
-       mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+       mips_cpu_irq_init();
        init_ioasic_irqs(IO_IRQ_BASE);
 
 }                              /* dec_init_kn02ca */
@@ -702,7 +702,7 @@ static void __init dec_init_kn03(void)
        memcpy(&asic_mask_nr_tbl, &kn03_asic_mask_nr_tbl,
                sizeof(kn03_asic_mask_nr_tbl));
 
-       mips_cpu_irq_init(DEC_CPU_IRQ_BASE);
+       mips_cpu_irq_init();
        init_ioasic_irqs(IO_IRQ_BASE);
 
 }                              /* dec_init_kn03 */
index 8d880f0b06ec1f1a0241ab5bfdd1d1fbfa70bb10..96df37b77759dd43be25f42abbfebe26467fa563 100644 (file)
@@ -57,7 +57,7 @@ static void emma2rh_irq_disable(unsigned int irq)
 }
 
 struct irq_chip emma2rh_irq_controller = {
-       .typename = "emma2rh_irq",
+       .name = "emma2rh_irq",
        .ack = emma2rh_irq_disable,
        .mask = emma2rh_irq_disable,
        .mask_ack = emma2rh_irq_disable,
index c93369cb411533d60d44f43516030e0822714353..3299b6dfe764435328887de1e7d0b23544e4ea93 100644 (file)
@@ -106,7 +106,7 @@ void __init arch_init_irq(void)
        emma2rh_irq_init(EMMA2RH_IRQ_BASE);
        emma2rh_sw_irq_init(EMMA2RH_SW_IRQ_BASE);
        emma2rh_gpio_irq_init(EMMA2RH_GPIO_IRQ_BASE);
-       mips_cpu_irq_init(CPU_IRQ_BASE);
+       mips_cpu_irq_init();
 
        /* setup cascade interrupts */
        setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade);
index 2116d9be5fa9185e20cd1c531f9f62bd28014732..fba5c156f47249fd04ad68fa14ff4f45c8463f2d 100644 (file)
@@ -49,7 +49,7 @@ static void emma2rh_sw_irq_disable(unsigned int irq)
 }
 
 struct irq_chip emma2rh_sw_irq_controller = {
-       .typename = "emma2rh_sw_irq",
+       .name = "emma2rh_sw_irq",
        .ack = emma2rh_sw_irq_disable,
        .mask = emma2rh_sw_irq_disable,
        .mask_ack = emma2rh_sw_irq_disable,
@@ -115,7 +115,7 @@ static void emma2rh_gpio_irq_end(unsigned int irq)
 }
 
 struct irq_chip emma2rh_gpio_irq_controller = {
-       .typename = "emma2rh_gpio_irq",
+       .name = "emma2rh_gpio_irq",
        .ack = emma2rh_gpio_irq_ack,
        .mask = emma2rh_gpio_irq_disable,
        .mask_ack = emma2rh_gpio_irq_ack,
index b3e5796c81d76e3229858acac6bba1b34d6b22d8..04572b9c964299a9a53c95b897031b0233de4bbd 100644 (file)
@@ -88,7 +88,7 @@ static void end_ev64120_irq(unsigned int irq)
 }
 
 static struct irq_chip ev64120_irq_type = {
-       .typename       = "EV64120",
+       .name           = "EV64120",
        .ack            = disable_ev64120_irq,
        .mask           = disable_ev64120_irq,
        .mask_ack       = disable_ev64120_irq,
index 99c8d42212e2c7973e3e8dc99388ff7fa1bd3594..477848c22a2c19bf4d491a48368bbc3b94aa163f 100644 (file)
@@ -59,9 +59,8 @@ extern void galileo_machine_power_off(void);
  */
 extern struct pci_ops galileo_pci_ops;
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 /*
index 2128684584f533a08b358793f5d45375b8f5e364..32d6fb4ee67955794547331adc8177e522d23784 100644 (file)
@@ -1,6 +1,4 @@
 
-#ifdef CONFIG_KGDB
-
 #include <asm/serial.h> /* For the serial port location and base baud */
 
 /* --- CONFIG --- */
@@ -121,5 +119,3 @@ int putDebugChar(uint8 byte)
        UART16550_WRITE(OFS_SEND_BUFFER, byte);
        return 1;
 }
-
-#endif
index d9294401ccb067a46510b00118407c4275bdb1bf..2585d9dbda33f9f5090d607e28c35b9ab486edf5 100644 (file)
@@ -90,6 +90,6 @@ void __init arch_init_irq(void)
        clear_c0_status(ST0_IM);
        local_irq_disable();
 
-       mips_cpu_irq_init(0);
-       rm7k_cpu_irq_init(8);
+       mips_cpu_irq_init();
+       rm7k_cpu_irq_init();
 }
index 8677b6d3ada7923243831b05da2be8630dba906c..78f393b2afd99efc374a8c48cd6f22692b6fa7c2 100644 (file)
@@ -67,7 +67,6 @@ void __init prom_init(void)
        add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
index eedfc24e1eae8c8004bacfa27f3f1443ed23a43c..d3d96591780e65412f363a8efd3e70c23c4dcbc6 100644 (file)
@@ -63,7 +63,7 @@ void gt64120_init_pic(void)
 void __init arch_init_irq(void)
 {
        /* IRQ 0 - 7 are for MIPS common irq_cpu controller */
-       mips_cpu_irq_init(0);
+       mips_cpu_irq_init();
 
        gt64120_init_pic();
 }
index 429afc400cb4ad4e7f7e071b1635a3a701a39103..121188d5ec4a3ee90660bf4c6c557001cd46afec 100644 (file)
@@ -93,9 +93,8 @@ void __init wrppmc_early_printk(const char *fmt, ...)
 }
 #endif /* WRPPMC_EARLY_DEBUG */
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 #ifdef CONFIG_SERIAL_8250
index f8d417b5c2bbd0f8bb85662db5139e1fefddeeb3..295892e4ce530a16c80109fd9e71325d4418fc4d 100644 (file)
@@ -40,7 +40,7 @@ void disable_r4030_irq(unsigned int irq)
 }
 
 static struct irq_chip r4030_irq_type = {
-       .typename = "R4030",
+       .name = "R4030",
        .ack = disable_r4030_irq,
        .mask = disable_r4030_irq,
        .mask_ack = disable_r4030_irq,
index 5d5838f41d23a3ea81fa1361505e5712e32acb59..aa481b774c42707ff539ad0f2e638330b9cce3b3 100644 (file)
@@ -75,7 +75,6 @@ void  __init prom_init_cmdline(void)
        *cp = '\0';
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
index 3da49c5aaf4947bcda20511d94419faca8d03b5d..7d2c203cb4067c232735c13189c1e515234dbe47 100644 (file)
@@ -439,7 +439,7 @@ void __init arch_init_irq(void)
 }
 
 static struct irq_chip jmr3927_irq_controller = {
-       .typename = "jmr3927_irq",
+       .name = "jmr3927_irq",
        .ack = jmr3927_irq_ack,
        .mask = jmr3927_irq_disable,
        .mask_ack = jmr3927_irq_ack,
index 138f25efe38a84fd82632dacc3efdcafd7da1436..7ca3d6d07b34f9c9998ed7e136c2722fcfbe9e92 100644 (file)
@@ -434,7 +434,7 @@ void __init tx3927_setup(void)
 
        /* DMA */
        tx3927_dmaptr->mcr = 0;
-       for (i = 0; i < sizeof(tx3927_dmaptr->ch) / sizeof(tx3927_dmaptr->ch[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(tx3927_dmaptr->ch); i++) {
                /* reset channel */
                tx3927_dmaptr->ch[i].ccr = TX3927_DMA_CCR_CHRST;
                tx3927_dmaptr->ch[i].ccr = 0;
index ff88b06f89df9b922ab616b4826162d4e23889ad..ea7df4b8da338d92822f35d72d96e52324415429 100644 (file)
@@ -234,10 +234,6 @@ void output_mm_defines(void)
        constant("#define _PMD_SHIFT     ", PMD_SHIFT);
        constant("#define _PGDIR_SHIFT   ", PGDIR_SHIFT);
        linefeed;
-       constant("#define _PGD_ORDER     ", PGD_ORDER);
-       constant("#define _PMD_ORDER     ", PMD_ORDER);
-       constant("#define _PTE_ORDER     ", PTE_ORDER);
-       linefeed;
        constant("#define _PTRS_PER_PGD  ", PTRS_PER_PGD);
        constant("#define _PTRS_PER_PMD  ", PTRS_PER_PMD);
        constant("#define _PTRS_PER_PTE  ", PTRS_PER_PTE);
index 442839e9578c3c21d4b3763c75a653c657d9757d..f59ef271d2472d97bc65e3a76ad74fc3088ee363 100644 (file)
@@ -565,7 +565,7 @@ static inline unsigned int decode_config3(struct cpuinfo_mips *c)
        if (config3 & MIPS_CONF3_VEIC)
                c->options |= MIPS_CPU_VEIC;
        if (config3 & MIPS_CONF3_MT)
-                c->ases |= MIPS_ASE_MIPSMT;
+               c->ases |= MIPS_ASE_MIPSMT;
 
        return config3 & MIPS_CONF_M;
 }
index 719d26968cb236675ef6a32bfd33cb836e3238f0..7bc882049269cf66dfa8c5221327faf682d46c48 100644 (file)
@@ -505,13 +505,13 @@ void show_gdbregs(struct gdb_regs * regs)
         */
        printk("$0 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
               regs->reg0, regs->reg1, regs->reg2, regs->reg3,
-               regs->reg4, regs->reg5, regs->reg6, regs->reg7);
+              regs->reg4, regs->reg5, regs->reg6, regs->reg7);
        printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
               regs->reg8, regs->reg9, regs->reg10, regs->reg11,
-               regs->reg12, regs->reg13, regs->reg14, regs->reg15);
+              regs->reg12, regs->reg13, regs->reg14, regs->reg15);
        printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
               regs->reg16, regs->reg17, regs->reg18, regs->reg19,
-               regs->reg20, regs->reg21, regs->reg22, regs->reg23);
+              regs->reg20, regs->reg21, regs->reg22, regs->reg23);
        printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
               regs->reg24, regs->reg25, regs->reg26, regs->reg27,
               regs->reg28, regs->reg29, regs->reg30, regs->reg31);
index 9a7811d13db2ac607439bd238968a6f17a87841c..6f57ca44291f98a445eeb99b294a67ada0d02a35 100644 (file)
@@ -231,28 +231,3 @@ NESTED(smp_bootstrap, 16, sp)
 #endif /* CONFIG_SMP */
 
        __FINIT
-
-       .comm   kernelsp,    NR_CPUS * 8, 8
-       .comm   pgd_current, NR_CPUS * 8, 8
-
-       .comm   fw_arg0, SZREG, SZREG           # firmware arguments
-       .comm   fw_arg1, SZREG, SZREG
-       .comm   fw_arg2, SZREG, SZREG
-       .comm   fw_arg3, SZREG, SZREG
-
-       .macro page name, order
-       .comm   \name, (_PAGE_SIZE << \order), (_PAGE_SIZE << \order)
-       .endm
-
-       /*
-        * On 64-bit we've got three-level pagetables with a slightly
-        * different layout ...
-        */
-       page    swapper_pg_dir, _PGD_ORDER
-#ifdef CONFIG_64BIT
-#if defined(CONFIG_MODULES) && !defined(CONFIG_BUILD_ELF64)
-       page    module_pg_dir, _PGD_ORDER
-#endif
-       page    invalid_pmd_table, _PMD_ORDER
-#endif
-       page    invalid_pte_table, _PTE_ORDER
index b59a676c6d0e392cfc19632449d3ffa6cc6b9314..b33ba6cd7f5bca912896746ed4cbec133169bcdc 100644 (file)
@@ -54,9 +54,11 @@ static unsigned int cached_irq_mask = 0xffff;
 
 void disable_8259A_irq(unsigned int irq)
 {
-       unsigned int mask = 1 << irq;
+       unsigned int mask;
        unsigned long flags;
 
+       irq -= I8259A_IRQ_BASE;
+       mask = 1 << irq;
        spin_lock_irqsave(&i8259A_lock, flags);
        cached_irq_mask |= mask;
        if (irq & 8)
@@ -68,9 +70,11 @@ void disable_8259A_irq(unsigned int irq)
 
 void enable_8259A_irq(unsigned int irq)
 {
-       unsigned int mask = ~(1 << irq);
+       unsigned int mask;
        unsigned long flags;
 
+       irq -= I8259A_IRQ_BASE;
+       mask = ~(1 << irq);
        spin_lock_irqsave(&i8259A_lock, flags);
        cached_irq_mask &= mask;
        if (irq & 8)
@@ -82,10 +86,12 @@ void enable_8259A_irq(unsigned int irq)
 
 int i8259A_irq_pending(unsigned int irq)
 {
-       unsigned int mask = 1 << irq;
+       unsigned int mask;
        unsigned long flags;
        int ret;
 
+       irq -= I8259A_IRQ_BASE;
+       mask = 1 << irq;
        spin_lock_irqsave(&i8259A_lock, flags);
        if (irq < 8)
                ret = inb(PIC_MASTER_CMD) & mask;
@@ -134,9 +140,11 @@ static inline int i8259A_irq_real(unsigned int irq)
  */
 void mask_and_ack_8259A(unsigned int irq)
 {
-       unsigned int irqmask = 1 << irq;
+       unsigned int irqmask;
        unsigned long flags;
 
+       irq -= I8259A_IRQ_BASE;
+       irqmask = 1 << irq;
        spin_lock_irqsave(&i8259A_lock, flags);
        /*
         * Lightweight spurious IRQ detection. We do not want
@@ -169,8 +177,8 @@ handle_real_irq:
                outb(0x60+irq,PIC_MASTER_CMD);  /* 'Specific EOI to master */
        }
 #ifdef CONFIG_MIPS_MT_SMTC
-        if (irq_hwmask[irq] & ST0_IM)
-               set_c0_status(irq_hwmask[irq] & ST0_IM);
+       if (irq_hwmask[irq] & ST0_IM)
+               set_c0_status(irq_hwmask[irq] & ST0_IM);
 #endif /* CONFIG_MIPS_MT_SMTC */
        spin_unlock_irqrestore(&i8259A_lock, flags);
        return;
@@ -322,8 +330,8 @@ void __init init_i8259_irqs (void)
 
        init_8259A(0);
 
-       for (i = 0; i < 16; i++)
+       for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++)
                set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq);
 
-       setup_irq(PIC_CASCADE_IR, &irq2);
+       setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
 }
index 37cad5de515c782c51d67e432640084c53b53de2..3cc25c05d367b942a2f355cd295292b763b3a281 100644 (file)
@@ -10,6 +10,8 @@
  * Copyright (C) 1996 - 2004 David S. Miller <dm@engr.sgi.com>
  * Copyright (C) 2004 - 2005 Steven J. Hill <sjhill@realitydiluted.com>
  */
+#undef DEBUG
+
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
@@ -40,8 +42,6 @@
 
 #include <linux/elf.h>
 
-#undef DEBUG
-
 static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs);
 static int load_irix_library(struct file *);
 static int irix_core_dump(long signr, struct pt_regs * regs,
@@ -52,72 +52,102 @@ static struct linux_binfmt irix_format = {
        irix_core_dump, PAGE_SIZE
 };
 
-#ifdef DEBUG
 /* Debugging routines. */
 static char *get_elf_p_type(Elf32_Word p_type)
 {
-       int i = (int) p_type;
-
-       switch(i) {
-       case PT_NULL: return("PT_NULL"); break;
-       case PT_LOAD: return("PT_LOAD"); break;
-       case PT_DYNAMIC: return("PT_DYNAMIC"); break;
-       case PT_INTERP: return("PT_INTERP"); break;
-       case PT_NOTE: return("PT_NOTE"); break;
-       case PT_SHLIB: return("PT_SHLIB"); break;
-       case PT_PHDR: return("PT_PHDR"); break;
-       case PT_LOPROC: return("PT_LOPROC/REGINFO"); break;
-       case PT_HIPROC: return("PT_HIPROC"); break;
-       default: return("PT_BOGUS"); break;
+#ifdef DEBUG
+       switch (p_type) {
+       case PT_NULL:
+               return "PT_NULL";
+               break;
+
+       case PT_LOAD:
+               return "PT_LOAD";
+               break;
+
+       case PT_DYNAMIC:
+               return "PT_DYNAMIC";
+               break;
+
+       case PT_INTERP:
+               return "PT_INTERP";
+               break;
+
+       case PT_NOTE:
+               return "PT_NOTE";
+               break;
+
+       case PT_SHLIB:
+               return "PT_SHLIB";
+               break;
+
+       case PT_PHDR:
+               return "PT_PHDR";
+               break;
+
+       case PT_LOPROC:
+               return "PT_LOPROC/REGINFO";
+               break;
+
+       case PT_HIPROC:
+               return "PT_HIPROC";
+               break;
+
+       default:
+               return "PT_BOGUS";
+               break;
        }
+#endif
 }
 
 static void print_elfhdr(struct elfhdr *ehp)
 {
        int i;
 
-       printk("ELFHDR: e_ident<");
-       for(i = 0; i < (EI_NIDENT - 1); i++) printk("%x ", ehp->e_ident[i]);
-       printk("%x>\n", ehp->e_ident[i]);
-       printk("        e_type[%04x] e_machine[%04x] e_version[%08lx]\n",
-              (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine,
-              (unsigned long) ehp->e_version);
-       printk("        e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] "
-              "e_flags[%08lx]\n",
-              (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff,
-              (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags);
-       printk("        e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n",
-              (unsigned short) ehp->e_ehsize, (unsigned short) ehp->e_phentsize,
-              (unsigned short) ehp->e_phnum);
-       printk("        e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n",
-              (unsigned short) ehp->e_shentsize, (unsigned short) ehp->e_shnum,
-              (unsigned short) ehp->e_shstrndx);
+       pr_debug("ELFHDR: e_ident<");
+       for (i = 0; i < (EI_NIDENT - 1); i++)
+               pr_debug("%x ", ehp->e_ident[i]);
+       pr_debug("%x>\n", ehp->e_ident[i]);
+       pr_debug("        e_type[%04x] e_machine[%04x] e_version[%08lx]\n",
+                (unsigned short) ehp->e_type, (unsigned short) ehp->e_machine,
+                (unsigned long) ehp->e_version);
+       pr_debug("        e_entry[%08lx] e_phoff[%08lx] e_shoff[%08lx] "
+                "e_flags[%08lx]\n",
+                (unsigned long) ehp->e_entry, (unsigned long) ehp->e_phoff,
+                (unsigned long) ehp->e_shoff, (unsigned long) ehp->e_flags);
+       pr_debug("        e_ehsize[%04x] e_phentsize[%04x] e_phnum[%04x]\n",
+                (unsigned short) ehp->e_ehsize,
+                (unsigned short) ehp->e_phentsize,
+                (unsigned short) ehp->e_phnum);
+       pr_debug("        e_shentsize[%04x] e_shnum[%04x] e_shstrndx[%04x]\n",
+                (unsigned short) ehp->e_shentsize,
+                (unsigned short) ehp->e_shnum,
+                (unsigned short) ehp->e_shstrndx);
 }
 
 static void print_phdr(int i, struct elf_phdr *ep)
 {
-       printk("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] "
-              "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type),
-              (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr,
-              (unsigned long) ep->p_paddr);
-       printk("         p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] "
-              "p_align[%08lx]\n", (unsigned long) ep->p_filesz,
-              (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags,
-              (unsigned long) ep->p_align);
+       pr_debug("PHDR[%d]: p_type[%s] p_offset[%08lx] p_vaddr[%08lx] "
+                "p_paddr[%08lx]\n", i, get_elf_p_type(ep->p_type),
+                (unsigned long) ep->p_offset, (unsigned long) ep->p_vaddr,
+                (unsigned long) ep->p_paddr);
+       pr_debug("         p_filesz[%08lx] p_memsz[%08lx] p_flags[%08lx] "
+                "p_align[%08lx]\n", (unsigned long) ep->p_filesz,
+                (unsigned long) ep->p_memsz, (unsigned long) ep->p_flags,
+                (unsigned long) ep->p_align);
 }
 
 static void dump_phdrs(struct elf_phdr *ep, int pnum)
 {
        int i;
 
-       for(i = 0; i < pnum; i++, ep++) {
-               if((ep->p_type == PT_LOAD) ||
-                  (ep->p_type == PT_INTERP) ||
-                  (ep->p_type == PT_PHDR))
+       for (i = 0; i < pnum; i++, ep++) {
+               if ((ep->p_type == PT_LOAD) ||
+                   (ep->p_type == PT_INTERP) ||
+                   (ep->p_type == PT_PHDR))
                        print_phdr(i, ep);
        }
 }
-#endif /* DEBUG */
 
 static void set_brk(unsigned long start, unsigned long end)
 {
@@ -156,11 +186,10 @@ static unsigned long * create_irix_tables(char * p, int argc, int envc,
        elf_addr_t *envp;
        elf_addr_t *sp, *csp;
 
-#ifdef DEBUG
-       printk("create_irix_tables: p[%p] argc[%d] envc[%d] "
-              "load_addr[%08x] interp_load_addr[%08x]\n",
-              p, argc, envc, load_addr, interp_load_addr);
-#endif
+       pr_debug("create_irix_tables: p[%p] argc[%d] envc[%d] "
+                "load_addr[%08x] interp_load_addr[%08x]\n",
+                p, argc, envc, load_addr, interp_load_addr);
+
        sp = (elf_addr_t *) (~15UL & (unsigned long) p);
        csp = sp;
        csp -= exec ? DLINFO_ITEMS*2 : 2;
@@ -181,7 +210,7 @@ static unsigned long * create_irix_tables(char * p, int argc, int envc,
        sp -= 2;
        NEW_AUX_ENT(0, AT_NULL, 0);
 
-       if(exec) {
+       if (exec) {
                sp -= 11*2;
 
                NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff);
@@ -245,9 +274,7 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
        last_bss = 0;
        error = load_addr = 0;
 
-#ifdef DEBUG
        print_elfhdr(interp_elf_ex);
-#endif
 
        /* First of all, some simple consistency checks */
        if ((interp_elf_ex->e_type != ET_EXEC &&
@@ -258,7 +285,7 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
        }
 
        /* Now read in all of the header information */
-       if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) {
+       if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) {
            printk("IRIX interp header bigger than a page (%d)\n",
                   (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum));
            return 0xffffffff;
@@ -267,15 +294,15 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
        elf_phdata = kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum,
                             GFP_KERNEL);
 
-       if(!elf_phdata) {
-          printk("Cannot kmalloc phdata for IRIX interp.\n");
-         return 0xffffffff;
+       if (!elf_phdata) {
+               printk("Cannot kmalloc phdata for IRIX interp.\n");
+               return 0xffffffff;
        }
 
        /* If the size of this structure has changed, then punt, since
         * we will be doing the wrong thing.
         */
-       if(interp_elf_ex->e_phentsize != 32) {
+       if (interp_elf_ex->e_phentsize != 32) {
                printk("IRIX interp e_phentsize == %d != 32 ",
                       interp_elf_ex->e_phentsize);
                kfree(elf_phdata);
@@ -286,61 +313,71 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
                           (char *) elf_phdata,
                           sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
 
-#ifdef DEBUG
        dump_phdrs(elf_phdata, interp_elf_ex->e_phnum);
-#endif
 
        eppnt = elf_phdata;
-       for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
-         if(eppnt->p_type == PT_LOAD) {
-           int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
-           int elf_prot = 0;
-           unsigned long vaddr = 0;
-           if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
-           if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
-           if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-           elf_type |= MAP_FIXED;
-           vaddr = eppnt->p_vaddr;
-
-           pr_debug("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
-                  interpreter, vaddr,
-                  (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)),
-                  (unsigned long) elf_prot, (unsigned long) elf_type,
-                  (unsigned long) (eppnt->p_offset & 0xfffff000));
-           down_write(&current->mm->mmap_sem);
-           error = do_mmap(interpreter, vaddr,
-                           eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
-                           elf_prot, elf_type,
-                           eppnt->p_offset & 0xfffff000);
-           up_write(&current->mm->mmap_sem);
-
-           if(error < 0 && error > -1024) {
-                   printk("Aieee IRIX interp mmap error=%d\n", error);
-                   break;  /* Real error */
-           }
-           pr_debug("error=%08lx ", (unsigned long) error);
-           if(!load_addr && interp_elf_ex->e_type == ET_DYN) {
-             load_addr = error;
-              pr_debug("load_addr = error ");
-           }
-
-           /* Find the end of the file  mapping for this phdr, and keep
-            * track of the largest address we see for this.
-            */
-           k = eppnt->p_vaddr + eppnt->p_filesz;
-           if(k > elf_bss) elf_bss = k;
-
-           /* Do the same thing for the memory mapping - between
-            * elf_bss and last_bss is the bss section.
-            */
-           k = eppnt->p_memsz + eppnt->p_vaddr;
-           if(k > last_bss) last_bss = k;
-           pr_debug("\n");
-         }
+       for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
+               if (eppnt->p_type == PT_LOAD) {
+                       int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+                       int elf_prot = 0;
+                       unsigned long vaddr = 0;
+                       if (eppnt->p_flags & PF_R)
+                               elf_prot =  PROT_READ;
+                       if (eppnt->p_flags & PF_W)
+                               elf_prot |= PROT_WRITE;
+                       if (eppnt->p_flags & PF_X)
+                               elf_prot |= PROT_EXEC;
+                       elf_type |= MAP_FIXED;
+                       vaddr = eppnt->p_vaddr;
+
+                       pr_debug("INTERP do_mmap"
+                                "(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
+                                interpreter, vaddr,
+                                (unsigned long)
+                                (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)),
+                                (unsigned long)
+                                elf_prot, (unsigned long) elf_type,
+                                (unsigned long)
+                                (eppnt->p_offset & 0xfffff000));
+
+                       down_write(&current->mm->mmap_sem);
+                       error = do_mmap(interpreter, vaddr,
+                       eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
+                       elf_prot, elf_type,
+                       eppnt->p_offset & 0xfffff000);
+                       up_write(&current->mm->mmap_sem);
+
+                       if (error < 0 && error > -1024) {
+                               printk("Aieee IRIX interp mmap error=%d\n",
+                                      error);
+                               break;  /* Real error */
+                       }
+                       pr_debug("error=%08lx ", (unsigned long) error);
+                       if (!load_addr && interp_elf_ex->e_type == ET_DYN) {
+                               load_addr = error;
+                               pr_debug("load_addr = error ");
+                       }
+
+                       /*
+                        * Find the end of the file  mapping for this phdr, and
+                        * keep track of the largest address we see for this.
+                        */
+                       k = eppnt->p_vaddr + eppnt->p_filesz;
+                       if (k > elf_bss)
+                               elf_bss = k;
+
+                       /* Do the same thing for the memory mapping - between
+                        * elf_bss and last_bss is the bss section.
+                        */
+                       k = eppnt->p_memsz + eppnt->p_vaddr;
+                       if (k > last_bss)
+                               last_bss = k;
+                       pr_debug("\n");
+               }
        }
 
        /* Now use mmap to map the library into memory. */
-       if(error < 0 && error > -1024) {
+       if (error < 0 && error > -1024) {
                pr_debug("got error %d\n", error);
                kfree(elf_phdata);
                return 0xffffffff;
@@ -377,7 +414,7 @@ static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm)
                return -ENOEXEC;
 
        /* First of all, some simple consistency checks */
-       if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) ||
+       if ((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) ||
            !bprm->file->f_op->mmap) {
                return -ENOEXEC;
        }
@@ -388,7 +425,7 @@ static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm)
         * XXX all registers as 64bits on cpu's capable of this at
         * XXX exception time plus frob the XTLB exception vector.
         */
-       if((ehp->e_flags & EF_MIPS_ABI2))
+       if ((ehp->e_flags & EF_MIPS_ABI2))
                return -ENOEXEC;
 
        return 0;
@@ -410,7 +447,7 @@ static inline int look_for_irix_interpreter(char **name,
        struct file *file = NULL;
 
        *name = NULL;
-       for(i = 0; i < pnum; i++, epp++) {
+       for (i = 0; i < pnum; i++, epp++) {
                if (epp->p_type != PT_INTERP)
                        continue;
 
@@ -467,8 +504,8 @@ static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnu
        unsigned int tmp;
        int i, prot;
 
-       for(i = 0; i < pnum; i++, epp++) {
-               if(epp->p_type != PT_LOAD)
+       for (i = 0; i < pnum; i++, epp++) {
+               if (epp->p_type != PT_LOAD)
                        continue;
 
                /* Map it. */
@@ -483,23 +520,23 @@ static inline void map_executable(struct file *fp, struct elf_phdr *epp, int pnu
                up_write(&current->mm->mmap_sem);
 
                /* Fixup location tracking vars. */
-               if((epp->p_vaddr & 0xfffff000) < *estack)
+               if ((epp->p_vaddr & 0xfffff000) < *estack)
                        *estack = (epp->p_vaddr & 0xfffff000);
-               if(!*laddr)
+               if (!*laddr)
                        *laddr = epp->p_vaddr - epp->p_offset;
-               if(epp->p_vaddr < *scode)
+               if (epp->p_vaddr < *scode)
                        *scode = epp->p_vaddr;
 
                tmp = epp->p_vaddr + epp->p_filesz;
-               if(tmp > *ebss)
+               if (tmp > *ebss)
                        *ebss = tmp;
-               if((epp->p_flags & PF_X) && *ecode < tmp)
+               if ((epp->p_flags & PF_X) && *ecode < tmp)
                        *ecode = tmp;
-               if(*edata < tmp)
+               if (*edata < tmp)
                        *edata = tmp;
 
                tmp = epp->p_vaddr + epp->p_memsz;
-               if(tmp > *ebrk)
+               if (tmp > *ebrk)
                        *ebrk = tmp;
        }
 
@@ -513,12 +550,12 @@ static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp,
        int i;
 
        *eentry = 0xffffffff;
-       for(i = 0; i < pnum; i++, epp++) {
-               if(epp->p_type != PT_INTERP)
+       for (i = 0; i < pnum; i++, epp++) {
+               if (epp->p_type != PT_INTERP)
                        continue;
 
                /* We should have fielded this error elsewhere... */
-               if(*eentry != 0xffffffff)
+               if (*eentry != 0xffffffff)
                        return -1;
 
                set_fs(old_fs);
@@ -604,9 +641,7 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        if (elf_ex.e_shnum > 20)
                goto out;
 
-#ifdef DEBUG
        print_elfhdr(&elf_ex);
-#endif
 
        /* Now read in all of the header information */
        size = elf_ex.e_phentsize * elf_ex.e_phnum;
@@ -622,13 +657,11 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        if (retval < 0)
                goto out_free_ph;
 
-#ifdef DEBUG
        dump_phdrs(elf_phdata, elf_ex.e_phnum);
-#endif
 
        /* Set some things for later. */
-       for(i = 0; i < elf_ex.e_phnum; i++) {
-               switch(elf_phdata[i].p_type) {
+       for (i = 0; i < elf_ex.e_phnum; i++) {
+               switch (elf_phdata[i].p_type) {
                case PT_INTERP:
                        has_interp = 1;
                        elf_ihdr = &elf_phdata[i];
@@ -667,7 +700,7 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
        if (elf_interpreter) {
                retval = verify_irix_interpreter(&interp_elf_ex);
-               if(retval)
+               if (retval)
                        goto out_free_interp;
        }
 
@@ -706,12 +739,12 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                       &load_addr, &start_code, &elf_bss, &end_code,
                       &end_data, &elf_brk);
 
-       if(elf_interpreter) {
+       if (elf_interpreter) {
                retval = map_interpreter(elf_phdata, &interp_elf_ex,
                                         interpreter, &interp_load_addr,
                                         elf_ex.e_phnum, old_fs, &elf_entry);
                kfree(elf_interpreter);
-               if(retval) {
+               if (retval) {
                        set_fs(old_fs);
                        printk("Unable to load IRIX ELF interpreter\n");
                        send_sig(SIGSEGV, current, 0);
@@ -809,12 +842,12 @@ static int load_irix_library(struct file *file)
                return -ENOEXEC;
 
        /* First of all, some simple consistency checks. */
-       if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
+       if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
           !file->f_op->mmap)
                return -ENOEXEC;
 
        /* Now read in all of the header information. */
-       if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
+       if (sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
                return -ENOEXEC;
 
        elf_phdata = kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
@@ -825,15 +858,15 @@ static int load_irix_library(struct file *file)
                           sizeof(struct elf_phdr) * elf_ex.e_phnum);
 
        j = 0;
-       for(i=0; i<elf_ex.e_phnum; i++)
-               if((elf_phdata + i)->p_type == PT_LOAD) j++;
+       for (i=0; i<elf_ex.e_phnum; i++)
+               if ((elf_phdata + i)->p_type == PT_LOAD) j++;
 
-       if(j != 1)  {
+       if (j != 1)  {
                kfree(elf_phdata);
                return -ENOEXEC;
        }
 
-       while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
+       while (elf_phdata->p_type != PT_LOAD) elf_phdata++;
 
        /* Now use mmap to map the library into memory. */
        down_write(&current->mm->mmap_sem);
@@ -889,9 +922,7 @@ unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt)
                return -EFAULT;
        }
 
-#ifdef DEBUG
        dump_phdrs(user_phdrp, cnt);
-#endif
 
        for (i = 0; i < cnt; i++, hp++) {
                if (__get_user(type, &hp->p_type))
@@ -905,14 +936,14 @@ unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt)
        filp = fget(fd);
        if (!filp)
                return -EACCES;
-       if(!filp->f_op) {
+       if (!filp->f_op) {
                printk("irix_mapelf: Bogon filp!\n");
                fput(filp);
                return -EACCES;
        }
 
        hp = user_phdrp;
-       for(i = 0; i < cnt; i++, hp++) {
+       for (i = 0; i < cnt; i++, hp++) {
                int prot;
 
                retval = __get_user(vaddr, &hp->p_vaddr);
@@ -1015,8 +1046,6 @@ static int notesize(struct memelfnote *en)
        return sz;
 }
 
-/* #define DEBUG */
-
 #define DUMP_WRITE(addr, nr)   \
        if (!dump_write(file, (addr), (nr))) \
                goto end_coredump;
@@ -1093,9 +1122,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
 
                segs++;
        }
-#ifdef DEBUG
-       printk("irix_core_dump: %d segs taking %d bytes\n", segs, size);
-#endif
+       pr_debug("irix_core_dump: %d segs taking %d bytes\n", segs, size);
 
        /* Set up header. */
        memcpy(elf.e_ident, ELFMAG, SELFMAG);
@@ -1221,7 +1248,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
                struct elf_phdr phdr;
                int sz = 0;
 
-               for(i = 0; i < numnote; i++)
+               for (i = 0; i < numnote; i++)
                        sz += notesize(&notes[i]);
 
                phdr.p_type = PT_NOTE;
@@ -1241,7 +1268,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
        dataoff = offset = roundup(offset, PAGE_SIZE);
 
        /* Write program headers for segments dump. */
-       for(vma = current->mm->mmap, i = 0;
+       for (vma = current->mm->mmap, i = 0;
                i < segs && vma != NULL; vma = vma->vm_next) {
                struct elf_phdr phdr;
                size_t sz;
@@ -1267,7 +1294,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
                DUMP_WRITE(&phdr, sizeof(phdr));
        }
 
-       for(i = 0; i < numnote; i++)
+       for (i = 0; i < numnote; i++)
                if (!writenote(&notes[i], file))
                        goto end_coredump;
 
@@ -1275,7 +1302,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
 
        DUMP_SEEK(dataoff);
 
-       for(i = 0, vma = current->mm->mmap;
+       for (i = 0, vma = current->mm->mmap;
            i < segs && vma != NULL;
            vma = vma->vm_next) {
                unsigned long addr = vma->vm_start;
@@ -1284,9 +1311,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file)
                if (!maydump(vma))
                        continue;
                i++;
-#ifdef DEBUG
-               printk("elf_core_dump: writing %08lx %lx\n", addr, len);
-#endif
+               pr_debug("elf_core_dump: writing %08lx %lx\n", addr, len);
                DUMP_WRITE((void __user *)addr, len);
        }
 
index bcaad6696082480c114c5cbc57e674e9ed2a3ea7..2967537221e2118929c3ac5816f8830bc2379033 100644 (file)
@@ -112,7 +112,7 @@ msc_bind_eic_interrupt (unsigned int irq, unsigned int set)
 }
 
 struct irq_chip msc_levelirq_type = {
-       .typename = "SOC-it-Level",
+       .name = "SOC-it-Level",
        .ack = level_mask_and_ack_msc_irq,
        .mask = mask_msc_irq,
        .mask_ack = level_mask_and_ack_msc_irq,
@@ -122,7 +122,7 @@ struct irq_chip msc_levelirq_type = {
 };
 
 struct irq_chip msc_edgeirq_type = {
-       .typename = "SOC-it-Edge",
+       .name = "SOC-it-Edge",
        .ack = edge_mask_and_ack_msc_irq,
        .mask = mask_msc_irq,
        .mask_ack = edge_mask_and_ack_msc_irq,
index efbd219845b573fbe9d3097f1b69383a7dc8ac13..3dd561832e4c91dbbc44041043924d6a51a64e6b 100644 (file)
@@ -23,13 +23,13 @@ static unsigned int irq_base;
 
 static inline int ls1bit32(unsigned int x)
 {
-        int b = 31, s;
+       int b = 31, s;
 
-        s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
-        s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
-        s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
-        s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
-        s =  1; if (x <<  1 == 0) s = 0; b -= s;
+       s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
+       s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
+       s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
+       s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
+       s =  1; if (x <<  1 == 0) s = 0; b -= s;
 
         return b;
 }
@@ -92,7 +92,7 @@ void ll_mv64340_irq(void)
 }
 
 struct irq_chip mv64340_irq_type = {
-       .typename = "MV-64340",
+       .name = "MV-64340",
        .ack = mask_mv64340_irq,
        .mask = mask_mv64340_irq,
        .mask_ack = mask_mv64340_irq,
index 123324ba8c14ca05c18562bd9cd7c5c25a794c08..2507328834886e7f6151799713cb1de5ae505fef 100644 (file)
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-static int irq_base;
-
 static inline void unmask_rm7k_irq(unsigned int irq)
 {
-       set_c0_intcontrol(0x100 << (irq - irq_base));
+       set_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE));
 }
 
 static inline void mask_rm7k_irq(unsigned int irq)
 {
-       clear_c0_intcontrol(0x100 << (irq - irq_base));
+       clear_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE));
 }
 
 static struct irq_chip rm7k_irq_controller = {
-       .typename = "RM7000",
+       .name = "RM7000",
        .ack = mask_rm7k_irq,
        .mask = mask_rm7k_irq,
        .mask_ack = mask_rm7k_irq,
        .unmask = unmask_rm7k_irq,
 };
 
-void __init rm7k_cpu_irq_init(int base)
+void __init rm7k_cpu_irq_init(void)
 {
+       int base = RM7K_CPU_IRQ_BASE;
        int i;
 
        clear_c0_intcontrol(0x00000f00);                /* Mask all */
@@ -46,6 +45,4 @@ void __init rm7k_cpu_irq_init(int base)
        for (i = base; i < base + 4; i++)
                set_irq_chip_and_handler(i, &rm7k_irq_controller,
                                         handle_level_irq);
-
-       irq_base = base;
 }
index 0e6f4c5349d2e86b0bd5cf2ecb3cfd6c2102ddd4..ae83d2df6f31d51dc47a223b45622add5633bd76 100644 (file)
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-static int irq_base;
-
 static inline void unmask_rm9k_irq(unsigned int irq)
 {
-       set_c0_intcontrol(0x1000 << (irq - irq_base));
+       set_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE));
 }
 
 static inline void mask_rm9k_irq(unsigned int irq)
 {
-       clear_c0_intcontrol(0x1000 << (irq - irq_base));
+       clear_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE));
 }
 
 static inline void rm9k_cpu_irq_enable(unsigned int irq)
@@ -39,15 +37,6 @@ static inline void rm9k_cpu_irq_enable(unsigned int irq)
        local_irq_restore(flags);
 }
 
-static void rm9k_cpu_irq_disable(unsigned int irq)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       mask_rm9k_irq(irq);
-       local_irq_restore(flags);
-}
-
 /*
  * Performance counter interrupts are global on all processors.
  */
@@ -81,7 +70,7 @@ static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
 }
 
 static struct irq_chip rm9k_irq_controller = {
-       .typename = "RM9000",
+       .name = "RM9000",
        .ack = mask_rm9k_irq,
        .mask = mask_rm9k_irq,
        .mask_ack = mask_rm9k_irq,
@@ -89,7 +78,7 @@ static struct irq_chip rm9k_irq_controller = {
 };
 
 static struct irq_chip rm9k_perfcounter_irq = {
-       .typename = "RM9000",
+       .name = "RM9000",
        .startup = rm9k_perfcounter_irq_startup,
        .shutdown = rm9k_perfcounter_irq_shutdown,
        .ack = mask_rm9k_irq,
@@ -102,8 +91,9 @@ unsigned int rm9000_perfcount_irq;
 
 EXPORT_SYMBOL(rm9000_perfcount_irq);
 
-void __init rm9k_cpu_irq_init(int base)
+void __init rm9k_cpu_irq_init(void)
 {
+       int base = RM9K_CPU_IRQ_BASE;
        int i;
 
        clear_c0_intcontrol(0x0000f000);                /* Mask all */
@@ -115,6 +105,4 @@ void __init rm9k_cpu_irq_init(int base)
        rm9000_perfcount_irq = base + 1;
        set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
                                 handle_level_irq);
-
-       irq_base = base;
 }
index fcc86b96ccf6097d5490dca91002b806936a9b89..7b66e03b58994e1e7f3daf6f88ead0628a1a4e12 100644 (file)
@@ -25,7 +25,7 @@
  * Don't even think about using this on SMP.  You have been warned.
  *
  * This file exports one global function:
- *     void mips_cpu_irq_init(int irq_base);
+ *     void mips_cpu_irq_init(void);
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/mipsmtregs.h>
 #include <asm/system.h>
 
-static int mips_cpu_irq_base;
-
 static inline void unmask_mips_irq(unsigned int irq)
 {
-       set_c0_status(0x100 << (irq - mips_cpu_irq_base));
+       set_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE));
        irq_enable_hazard();
 }
 
 static inline void mask_mips_irq(unsigned int irq)
 {
-       clear_c0_status(0x100 << (irq - mips_cpu_irq_base));
+       clear_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE));
        irq_disable_hazard();
 }
 
 static struct irq_chip mips_cpu_irq_controller = {
-       .typename       = "MIPS",
+       .name           = "MIPS",
        .ack            = mask_mips_irq,
        .mask           = mask_mips_irq,
        .mask_ack       = mask_mips_irq,
@@ -70,7 +68,7 @@ static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
 {
        unsigned int vpflags = dvpe();
 
-       clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+       clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE));
        evpe(vpflags);
        unmask_mips_mt_irq(irq);
 
@@ -84,13 +82,13 @@ static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
 static void mips_mt_cpu_irq_ack(unsigned int irq)
 {
        unsigned int vpflags = dvpe();
-       clear_c0_cause(0x100 << (irq - mips_cpu_irq_base));
+       clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE));
        evpe(vpflags);
        mask_mips_mt_irq(irq);
 }
 
 static struct irq_chip mips_mt_cpu_irq_controller = {
-       .typename       = "MIPS",
+       .name           = "MIPS",
        .startup        = mips_mt_cpu_irq_startup,
        .ack            = mips_mt_cpu_irq_ack,
        .mask           = mask_mips_mt_irq,
@@ -99,8 +97,9 @@ static struct irq_chip mips_mt_cpu_irq_controller = {
        .eoi            = unmask_mips_mt_irq,
 };
 
-void __init mips_cpu_irq_init(int irq_base)
+void __init mips_cpu_irq_init(void)
 {
+       int irq_base = MIPS_CPU_IRQ_BASE;
        int i;
 
        /* Mask interrupts. */
@@ -118,6 +117,4 @@ void __init mips_cpu_irq_init(int irq_base)
        for (i = irq_base + 2; i < irq_base + 8; i++)
                set_irq_chip_and_handler(i, &mips_cpu_irq_controller,
                                         handle_level_irq);
-
-       mips_cpu_irq_base = irq_base;
 }
index de3fae260ff82fb4e94655d1cc261d42d919dc74..0b8ce59429a8d1e3e73a6fe22cfe9b61b6429b40 100644 (file)
@@ -194,15 +194,15 @@ sysn32_waitid(int which, compat_pid_t pid,
 }
 
 struct sysinfo32 {
-        s32 uptime;
-        u32 loads[3];
-        u32 totalram;
-        u32 freeram;
-        u32 sharedram;
-        u32 bufferram;
-        u32 totalswap;
-        u32 freeswap;
-        u16 procs;
+       s32 uptime;
+       u32 loads[3];
+       u32 totalram;
+       u32 freeram;
+       u32 sharedram;
+       u32 bufferram;
+       u32 totalswap;
+       u32 freeswap;
+       u16 procs;
        u32 totalhigh;
        u32 freehigh;
        u32 mem_unit;
@@ -558,7 +558,7 @@ extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf);
 asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32)
 {
        int err;
-        struct ustat tmp;
+       struct ustat tmp;
        struct ustat32 tmp32;
        mm_segment_t old_fs = get_fs();
 
@@ -569,11 +569,11 @@ asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32)
        if (err)
                goto out;
 
-        memset(&tmp32,0,sizeof(struct ustat32));
-        tmp32.f_tfree = tmp.f_tfree;
-        tmp32.f_tinode = tmp.f_tinode;
+       memset(&tmp32,0,sizeof(struct ustat32));
+       tmp32.f_tfree = tmp.f_tfree;
+       tmp32.f_tinode = tmp.f_tinode;
 
-        err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;
+       err = copy_to_user(ubuf32,&tmp32,sizeof(struct ustat32)) ? -EFAULT : 0;
 
 out:
        return err;
index c1373a6e668bec45583c7ff498e697b0a30355ca..a32f6797353aa32fc6b25b770a1b867cf62f2909 100644 (file)
@@ -96,6 +96,10 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
                goto out_unlock;
        }
 
+       retval = security_task_setscheduler(p, 0, NULL);
+       if (retval)
+               goto out_unlock;
+
        /* Record new user-specified CPU set for future reference */
        p->thread.user_cpus_allowed = new_mask;
 
@@ -141,8 +145,9 @@ asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
        p = find_process_by_pid(pid);
        if (!p)
                goto out_unlock;
-
-       retval = 0;
+       retval = security_task_getscheduler(p);
+       if (retval)
+               goto out_unlock;
 
        cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
 
index 4ed37ba19731071b369180cd12d3895ece7becbe..5ddc2e9deecf3cfa042976c33b9b932c7d27edbe 100644 (file)
@@ -31,13 +31,13 @@ static const char *cpu_name[] = {
        [CPU_R4000PC]   = "R4000PC",
        [CPU_R4000SC]   = "R4000SC",
        [CPU_R4000MC]   = "R4000MC",
-        [CPU_R4200]    = "R4200",
+       [CPU_R4200]     = "R4200",
        [CPU_R4400PC]   = "R4400PC",
        [CPU_R4400SC]   = "R4400SC",
        [CPU_R4400MC]   = "R4400MC",
        [CPU_R4600]     = "R4600",
        [CPU_R6000]     = "R6000",
-        [CPU_R6000A]   = "R6000A",
+       [CPU_R6000A]    = "R6000A",
        [CPU_R8000]     = "R8000",
        [CPU_R10000]    = "R10000",
        [CPU_R12000]    = "R12000",
@@ -46,14 +46,14 @@ static const char *cpu_name[] = {
        [CPU_R4650]     = "R4650",
        [CPU_R4700]     = "R4700",
        [CPU_R5000]     = "R5000",
-        [CPU_R5000A]   = "R5000A",
+       [CPU_R5000A]    = "R5000A",
        [CPU_R4640]     = "R4640",
        [CPU_NEVADA]    = "Nevada",
        [CPU_RM7000]    = "RM7000",
        [CPU_RM9000]    = "RM9000",
        [CPU_R5432]     = "R5432",
        [CPU_4KC]       = "MIPS 4Kc",
-        [CPU_5KC]      = "MIPS 5Kc",
+       [CPU_5KC]       = "MIPS 5Kc",
        [CPU_R4310]     = "R4310",
        [CPU_SB1]       = "SiByte SB1",
        [CPU_SB1A]      = "SiByte SB1A",
index ec8209f3a0c68af6c70df1e43403ab23687f62f6..04e5b38d327de7e5bee477f43aeb3e8d46abb985 100644 (file)
 #include <asm/isadep.h>
 #include <asm/inst.h>
 #include <asm/stacktrace.h>
-#ifdef CONFIG_MIPS_MT_SMTC
-#include <asm/mipsmtregs.h>
-extern void smtc_idle_loop_hook(void);
-#endif /* CONFIG_MIPS_MT_SMTC */
 
 /*
  * The idle thread. There's no useful work to be done, so just try to conserve
@@ -57,6 +53,8 @@ ATTRIB_NORET void cpu_idle(void)
        while (1) {
                while (!need_resched()) {
 #ifdef CONFIG_MIPS_MT_SMTC
+                       extern void smtc_idle_loop_hook(void);
+
                        smtc_idle_loop_hook();
 #endif /* CONFIG_MIPS_MT_SMTC */
                        if (cpu_wait)
index 880fa6e841ee95f678993fb5dd17138f62f5af22..59c1577ecbb31e303dd8aa00d99d5dc3dfd4e13f 100644 (file)
@@ -114,6 +114,14 @@ LEAF(_save_fp_context32)
  */
 LEAF(_restore_fp_context)
        EX      lw t0, SC_FPC_CSR(a0)
+
+       /* Fail if the CSR has exceptions pending */
+       srl     t1, t0, 5
+       and     t1, t0
+       andi    t1, 0x1f << 7
+       bnez    t1, fault
+        nop
+
 #ifdef CONFIG_64BIT
        EX      ldc1 $f1, SC_FPREGS+8(a0)
        EX      ldc1 $f3, SC_FPREGS+24(a0)
@@ -157,6 +165,14 @@ LEAF(_restore_fp_context)
 LEAF(_restore_fp_context32)
        /* Restore an o32 sigcontext.  */
        EX      lw t0, SC32_FPC_CSR(a0)
+
+       /* Fail if the CSR has exceptions pending */
+       srl     t1, t0, 5
+       and     t1, t0
+       andi    t1, 0x1f << 7
+       bnez    t1, fault
+        nop
+
        EX      ldc1 $f0, SC32_FPREGS+0(a0)
        EX      ldc1 $f2, SC32_FPREGS+16(a0)
        EX      ldc1 $f4, SC32_FPREGS+32(a0)
@@ -177,9 +193,10 @@ LEAF(_restore_fp_context32)
        jr      ra
         li     v0, 0                                   # success
        END(_restore_fp_context32)
-       .set    reorder
 #endif
 
+       .set    reorder
+
        .type   fault@function
        .ent    fault
 fault: li      v0, -EFAULT                             # failure
index 5a99e3e0c96dcdab47d209ad4b4f3297d69e560a..8610f4a925e90a043a4ebd17ccddb5c899f98e0f 100644 (file)
@@ -63,7 +63,7 @@ extern void *vpe_get_shared(int index);
 
 static void rtlx_dispatch(void)
 {
-       do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ);
+       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ);
 }
 
 
@@ -491,7 +491,7 @@ static struct irqaction rtlx_irq = {
        .name           = "RTLX",
 };
 
-static int rtlx_irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
+static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ;
 
 static char register_chrdev_failed[] __initdata =
        KERN_ERR "rtlx_module_init: unable to register device\n";
index a7bff2a547235b4962c9c6f557f999ffcc88c534..39add2341aa296f303f0d4f0b0d18c67aa232a74 100644 (file)
@@ -384,7 +384,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_readlinkat
        PTR     sys_fchmodat
        PTR     sys_faccessat
-       PTR     sys_pselect6
+       PTR     compat_sys_pselect6
        PTR     sys_ppoll                       /* 6265 */
        PTR     sys_unshare
        PTR     sys_splice
index e91379c1be1d79826b81ca48182444ec2ad6deca..c58b8e0105ea0db8fa4cc2994324fddde7a4d17b 100644 (file)
@@ -506,7 +506,7 @@ sys_call_table:
        PTR     sys_readlinkat
        PTR     sys_fchmodat
        PTR     sys_faccessat                   /* 4300 */
-       PTR     sys_pselect6
+       PTR     compat_sys_pselect6
        PTR     sys_ppoll
        PTR     sys_unshare
        PTR     sys_splice
index 89440a0d8528f8ddf9b173f405f20b52723b8051..d2e01e7167b86a2e644d5d12d0fc2647ce1b5c8a 100644 (file)
@@ -271,8 +271,7 @@ static void __init bootmem_init(void)
 static void __init bootmem_init(void)
 {
        unsigned long reserved_end;
-       unsigned long highest = 0;
-       unsigned long mapstart = -1UL;
+       unsigned long mapstart = ~0UL;
        unsigned long bootmap_size;
        int i;
 
@@ -283,6 +282,13 @@ static void __init bootmem_init(void)
         */
        reserved_end = max(init_initrd(), PFN_UP(__pa_symbol(&_end)));
 
+       /*
+        * max_low_pfn is not a number of pages. The number of pages
+        * of the system is given by 'max_low_pfn - min_low_pfn'.
+        */
+       min_low_pfn = ~0UL;
+       max_low_pfn = 0;
+
        /*
         * Find the highest page frame number we have available.
         */
@@ -296,8 +302,10 @@ static void __init bootmem_init(void)
                end = PFN_DOWN(boot_mem_map.map[i].addr
                                + boot_mem_map.map[i].size);
 
-               if (end > highest)
-                       highest = end;
+               if (end > max_low_pfn)
+                       max_low_pfn = end;
+               if (start < min_low_pfn)
+                       min_low_pfn = start;
                if (end <= reserved_end)
                        continue;
                if (start >= mapstart)
@@ -305,22 +313,36 @@ static void __init bootmem_init(void)
                mapstart = max(reserved_end, start);
        }
 
+       if (min_low_pfn >= max_low_pfn)
+               panic("Incorrect memory mapping !!!");
+       if (min_low_pfn > ARCH_PFN_OFFSET) {
+               printk(KERN_INFO
+                      "Wasting %lu bytes for tracking %lu unused pages\n",
+                      (min_low_pfn - ARCH_PFN_OFFSET) * sizeof(struct page),
+                      min_low_pfn - ARCH_PFN_OFFSET);
+       } else if (min_low_pfn < ARCH_PFN_OFFSET) {
+               printk(KERN_INFO
+                      "%lu free pages won't be used\n",
+                      ARCH_PFN_OFFSET - min_low_pfn);
+       }
+       min_low_pfn = ARCH_PFN_OFFSET;
+
        /*
         * Determine low and high memory ranges
         */
-       if (highest > PFN_DOWN(HIGHMEM_START)) {
+       if (max_low_pfn > PFN_DOWN(HIGHMEM_START)) {
 #ifdef CONFIG_HIGHMEM
                highstart_pfn = PFN_DOWN(HIGHMEM_START);
-               highend_pfn = highest;
+               highend_pfn = max_low_pfn;
 #endif
-               highest = PFN_DOWN(HIGHMEM_START);
+               max_low_pfn = PFN_DOWN(HIGHMEM_START);
        }
 
        /*
         * Initialize the boot-time allocator with low memory only.
         */
-       bootmap_size = init_bootmem(mapstart, highest);
-
+       bootmap_size = init_bootmem_node(NODE_DATA(0), mapstart,
+                                        min_low_pfn, max_low_pfn);
        /*
         * Register fully available low RAM pages with the bootmem allocator.
         */
@@ -507,9 +529,9 @@ void __init setup_arch(char **cmdline_p)
 
 #if defined(CONFIG_VT)
 #if defined(CONFIG_VGA_CONSOLE)
-        conswitchp = &vga_con;
+       conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
-        conswitchp = &dummy_con;
+       conswitchp = &dummy_con;
 #endif
 #endif
 
@@ -541,3 +563,6 @@ int __init dsp_disable(char *s)
 }
 
 __setup("nodsp", dsp_disable);
+
+unsigned long kernelsp[NR_CPUS];
+unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
index b9d358e052144bb501956da1afca37553ab58394..9a44053cd9f18143521584d27165064bddbd254d 100644 (file)
@@ -89,7 +89,7 @@ _sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
        spin_lock_irq(&current->sighand->siglock);
        current->saved_sigmask = current->blocked;
        current->blocked = newset;
-        recalc_sigpending();
+       recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
        current->state = TASK_INTERRUPTIBLE;
@@ -124,7 +124,7 @@ asmlinkage int sys_sigaction(int sig, const struct sigaction __user *act,
 
        if (!ret && oact) {
                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
-                        return -EFAULT;
+                       return -EFAULT;
                err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
                err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
                err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
@@ -304,7 +304,7 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
               current->comm, current->pid,
               frame, regs->cp0_epc, frame->regs[31]);
 #endif
-        return 0;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(signr, current);
index a67c18555ed396cdb2c08443a1808dd2d39bda94..b28646b3ceaea8d04eaab8336206fbee571fb129 100644 (file)
@@ -105,7 +105,7 @@ _sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
        spin_lock_irq(&current->sighand->siglock);
        current->saved_sigmask = current->blocked;
        current->blocked = newset;
-        recalc_sigpending();
+       recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
        current->state = TASK_INTERRUPTIBLE;
@@ -184,7 +184,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
        /* Create the ucontext.  */
        err |= __put_user(0, &frame->rs_uc.uc_flags);
        err |= __put_user(0, &frame->rs_uc.uc_link);
-        sp = (int) (long) current->sas_ss_sp;
+       sp = (int) (long) current->sas_ss_sp;
        err |= __put_user(sp,
                          &frame->rs_uc.uc_stack.ss_sp);
        err |= __put_user(sas_ss_flags(regs->regs[29]),
index 1ee689c0e0c991b9537ec6b170b59614b9fd4f89..64b62bdfb4f62d46c3f5aa897bbfeec56e73b88b 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
 #include <asm/mips_mt.h>
-#include <asm/mips-boards/maltaint.h>  /* This is f*cking wrong */
 
 #define MIPS_CPU_IPI_RESCHED_IRQ 0
 #define MIPS_CPU_IPI_CALL_IRQ 1
@@ -108,12 +107,12 @@ void __init sanitize_tlb_entries(void)
 
 static void ipi_resched_dispatch(void)
 {
-       do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
+       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
 }
 
 static void ipi_call_dispatch(void)
 {
-       do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ);
+       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
 }
 
 static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
@@ -270,8 +269,8 @@ void __init plat_prepare_cpus(unsigned int max_cpus)
                set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
        }
 
-       cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
-       cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ;
+       cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
+       cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ;
 
        setup_irq(cpu_ipi_resched_irq, &irq_resched);
        setup_irq(cpu_ipi_call_irq, &irq_call);
index 6a857bf030b070aee2d9861e727cfd3605e62200..9251ea82493746a4829e69ba3f433f123e94eb24 100644 (file)
  * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set.
  */
 
-/*
- * MIPSCPU_INT_BASE is identically defined in both
- * asm-mips/mips-boards/maltaint.h and asm-mips/mips-boards/simint.h,
- * but as yet there's no properly organized include structure that
- * will ensure that the right *int.h file will be included for a
- * given platform build.
- */
-
-#define MIPSCPU_INT_BASE       16
-
 #define MIPS_CPU_IPI_IRQ       1
 
 #define LOCK_MT_PRA() \
@@ -77,15 +67,15 @@ unsigned int ipi_timer_latch[NR_CPUS];
 
 #define IPIBUF_PER_CPU 4
 
-struct smtc_ipi_q IPIQ[NR_CPUS];
-struct smtc_ipi_q freeIPIq;
+static struct smtc_ipi_q IPIQ[NR_CPUS];
+static struct smtc_ipi_q freeIPIq;
 
 
 /* Forward declarations */
 
 void ipi_decode(struct smtc_ipi *);
-void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
-void setup_cross_vpe_interrupts(void);
+static void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
+static void setup_cross_vpe_interrupts(void);
 void init_smtc_stats(void);
 
 /* Global SMTC Status */
@@ -200,7 +190,7 @@ void __init sanitize_tlb_entries(void)
  * Configure shared TLB - VPC configuration bit must be set by caller
  */
 
-void smtc_configure_tlb(void)
+static void smtc_configure_tlb(void)
 {
        int i,tlbsiz,vpes;
        unsigned long mvpconf0;
@@ -648,7 +638,7 @@ int setup_irq_smtc(unsigned int irq, struct irqaction * new,
  * the VPE.
  */
 
-void smtc_ipi_qdump(void)
+static void smtc_ipi_qdump(void)
 {
        int i;
 
@@ -686,28 +676,6 @@ static __inline__ int atomic_postincrement(unsigned int *pv)
        return result;
 }
 
-/* No longer used in IPI dispatch, but retained for future recycling */
-
-static __inline__ int atomic_postclear(unsigned int *pv)
-{
-       unsigned long result;
-
-       unsigned long temp;
-
-       __asm__ __volatile__(
-       "1:     ll      %0, %2                                  \n"
-       "       or      %1, $0, $0                              \n"
-       "       sc      %1, %2                                  \n"
-       "       beqz    %1, 1b                                  \n"
-       "       sync                                            \n"
-       : "=&r" (result), "=&r" (temp), "=m" (*pv)
-       : "m" (*pv)
-       : "memory");
-
-       return result;
-}
-
-
 void smtc_send_ipi(int cpu, int type, unsigned int action)
 {
        int tcstatus;
@@ -781,7 +749,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
 /*
  * Send IPI message to Halted TC, TargTC/TargVPE already having been set
  */
-void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
+static void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
 {
        struct pt_regs *kstack;
        unsigned long tcstatus;
@@ -921,7 +889,7 @@ void smtc_timer_broadcast(int vpe)
  * interrupts.
  */
 
-static int cpu_ipi_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_IRQ;
+static int cpu_ipi_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_IRQ;
 
 static irqreturn_t ipi_interrupt(int irq, void *dev_idm)
 {
@@ -1000,7 +968,7 @@ static void ipi_irq_dispatch(void)
 
 static struct irqaction irq_ipi;
 
-void setup_cross_vpe_interrupts(void)
+static void setup_cross_vpe_interrupts(void)
 {
        if (!cpu_has_vint)
                panic("SMTC Kernel requires Vectored Interupt support");
@@ -1191,7 +1159,7 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
         * It would be nice to be able to use a spinlock here,
         * but this is invoked from within TLB flush routines
         * that protect themselves with DVPE, so if a lock is
-         * held by another TC, it'll never be freed.
+        * held by another TC, it'll never be freed.
         *
         * DVPE/DMT must not be done with interrupts enabled,
         * so even so most callers will already have disabled
@@ -1296,7 +1264,7 @@ void smtc_flush_tlb_asid(unsigned long asid)
  * Support for single-threading cache flush operations.
  */
 
-int halt_state_save[NR_CPUS];
+static int halt_state_save[NR_CPUS];
 
 /*
  * To really, really be sure that nothing is being done
index 6c2406a93f2b99f1912d48d94788c5b65ebe2279..93a148486f88893a7464c51bfd16f3c93474444f 100644 (file)
@@ -669,7 +669,7 @@ asmlinkage int irix_mount(char __user *dev_name, char __user *dir_name,
 
 struct irix_statfs {
        short f_type;
-        long  f_bsize, f_frsize, f_blocks, f_bfree, f_files, f_ffree;
+       long  f_bsize, f_frsize, f_blocks, f_bfree, f_files, f_ffree;
        char  f_fname[6], f_fpack[6];
 };
 
@@ -959,7 +959,7 @@ static inline loff_t llseek(struct file *file, loff_t offset, int origin)
 
        fn = default_llseek;
        if (file->f_op && file->f_op->llseek)
-        fn = file->f_op->llseek;
+       fn = file->f_op->llseek;
        lock_kernel();
        retval = fn(file, offset, origin);
        unlock_kernel();
index 458fccf87c54ec436adb6bc9fb43c3bc84fbef32..459624969c99739d24b90aee8ca8bcdb6f52bd53 100644 (file)
@@ -522,7 +522,7 @@ static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
 };
 
 static char *rstrs[] = {
-       [R_MIPS_NONE]   = "MIPS_NONE",
+       [R_MIPS_NONE]   = "MIPS_NONE",
        [R_MIPS_32]     = "MIPS_32",
        [R_MIPS_26]     = "MIPS_26",
        [R_MIPS_HI16]   = "MIPS_HI16",
@@ -695,7 +695,7 @@ static void dump_tclist(void)
 }
 
 /* We are prepared so configure and start the VPE... */
-int vpe_run(struct vpe * v)
+static int vpe_run(struct vpe * v)
 {
        struct vpe_notifications *n;
        unsigned long val, dmt_flag;
@@ -713,16 +713,16 @@ int vpe_run(struct vpe * v)
        dvpe();
 
        if (!list_empty(&v->tc)) {
-                if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
-                        printk(KERN_WARNING "VPE loader: TC %d is already in use.\n",
-                               t->index);
-                        return -ENOEXEC;
-                }
-        } else {
-                printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n",
-                       v->minor);
-                return -ENOEXEC;
-        }
+               if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
+                       printk(KERN_WARNING "VPE loader: TC %d is already in use.\n",
+                              t->index);
+                       return -ENOEXEC;
+               }
+       } else {
+               printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n",
+                      v->minor);
+               return -ENOEXEC;
+       }
 
        /* Put MVPE's into 'configuration state' */
        set_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -775,14 +775,14 @@ int vpe_run(struct vpe * v)
 
        back_to_back_c0_hazard();
 
-        /* Set up the XTC bit in vpeconf0 to point at our tc */
-        write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
-                               | (t->index << VPECONF0_XTC_SHIFT));
+       /* Set up the XTC bit in vpeconf0 to point at our tc */
+       write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
+                             | (t->index << VPECONF0_XTC_SHIFT));
 
        back_to_back_c0_hazard();
 
-        /* enable this VPE */
-        write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
+       /* enable this VPE */
+       write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
 
        /* clear out any left overs from a previous program */
        write_vpe_c0_status(0);
@@ -832,7 +832,7 @@ static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
  * contents of the program (p)buffer performing relocatations/etc, free's it
  * when finished.
  */
-int vpe_elfload(struct vpe * v)
+static int vpe_elfload(struct vpe * v)
 {
        Elf_Ehdr *hdr;
        Elf_Shdr *sechdrs;
index 2affa5ff171c763e76067f96b2c7925a82b4e47d..9a622b9a105161bddcd068c3c9eedc55a25c8da6 100644 (file)
@@ -45,7 +45,7 @@ void enable_lasat_irq(unsigned int irq_nr)
 }
 
 static struct irq_chip lasat_irq_type = {
-       .typename = "Lasat",
+       .name = "Lasat",
        .ack = disable_lasat_irq,
        .mask = disable_lasat_irq,
        .mask_ack = disable_lasat_irq,
index 88c7ab871ec44bbe0c4f7dae9a92ca5c58b36da7..d47692f73a26ee0f619428526eb45535f631ab3e 100644 (file)
@@ -132,9 +132,8 @@ void __init prom_init(void)
        add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM);
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 const char *get_system_type(void)
index dcd4d2ed2ac45737e148cfd3a5d74460f5ff1cac..2036cf5e6857fe924e3bd934b9a01535afacdec5 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y  += memset.o watch.o
+lib-y  += watch.o
 
 obj-$(CONFIG_CPU_MIPS32)       += dump_tlb.o
 obj-$(CONFIG_CPU_MIPS64)       += dump_tlb.o
index dcd4d2ed2ac45737e148cfd3a5d74460f5ff1cac..2036cf5e6857fe924e3bd934b9a01535afacdec5 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y  += memset.o watch.o
+lib-y  += watch.o
 
 obj-$(CONFIG_CPU_MIPS32)       += dump_tlb.o
 obj-$(CONFIG_CPU_MIPS64)       += dump_tlb.o
diff --git a/arch/mips/lib-64/memset.S b/arch/mips/lib-64/memset.S
deleted file mode 100644 (file)
index e2c42c8..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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) 1998, 1999, 2000 by Ralf Baechle
- * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/asm-offsets.h>
-#include <asm/regdef.h>
-
-#define EX(insn,reg,addr,handler)                      \
-9:     insn    reg, addr;                              \
-       .section __ex_table,"a";                        \
-       PTR     9b, handler;                            \
-       .previous
-
-       .macro  f_fill64 dst, offset, val, fixup
-       EX(LONG_S, \val, (\offset +  0 * LONGSIZE)(\dst), \fixup)
-       EX(LONG_S, \val, (\offset +  1 * LONGSIZE)(\dst), \fixup)
-       EX(LONG_S, \val, (\offset +  2 * LONGSIZE)(\dst), \fixup)
-       EX(LONG_S, \val, (\offset +  3 * LONGSIZE)(\dst), \fixup)
-       EX(LONG_S, \val, (\offset +  4 * LONGSIZE)(\dst), \fixup)
-       EX(LONG_S, \val, (\offset +  5 * LONGSIZE)(\dst), \fixup)
-       EX(LONG_S, \val, (\offset +  6 * LONGSIZE)(\dst), \fixup)
-       EX(LONG_S, \val, (\offset +  7 * LONGSIZE)(\dst), \fixup)
-       .endm
-
-/*
- * memset(void *s, int c, size_t n)
- *
- * a0: start of area to clear
- * a1: char to fill with
- * a2: size of area to clear
- */
-       .set    noreorder
-       .align  5
-LEAF(memset)
-       beqz            a1, 1f
-        move           v0, a0                  /* result */
-
-       andi            a1, 0xff                /* spread fillword */
-       dsll            t1, a1, 8
-       or              a1, t1
-       dsll            t1, a1, 16
-       or              a1, t1
-       dsll            t1, a1, 32
-       or              a1, t1
-1:
-
-FEXPORT(__bzero)
-       sltiu           t0, a2, LONGSIZE        /* very small region? */
-       bnez            t0, small_memset
-        andi           t0, a0, LONGMASK        /* aligned? */
-
-       beqz            t0, 1f
-        PTR_SUBU       t0, LONGSIZE            /* alignment in bytes */
-
-#ifdef __MIPSEB__
-       EX(sdl, a1, (a0), first_fixup)          /* make dword aligned */
-#endif
-#ifdef __MIPSEL__
-       EX(sdr, a1, (a0), first_fixup)          /* make dword aligned */
-#endif
-       PTR_SUBU        a0, t0                  /* long align ptr */
-       PTR_ADDU        a2, t0                  /* correct size */
-
-1:     ori             t1, a2, 0x3f            /* # of full blocks */
-       xori            t1, 0x3f
-       beqz            t1, memset_partial      /* no block to fill */
-        andi           t0, a2, 0x38
-
-       PTR_ADDU        t1, a0                  /* end address */
-       .set            reorder
-1:     PTR_ADDIU       a0, 64
-       f_fill64 a0, -64, a1, fwd_fixup
-       bne             t1, a0, 1b
-       .set            noreorder
-
-memset_partial:
-       PTR_LA          t1, 2f                  /* where to start */
-       .set            noat
-       dsrl            AT, t0, 1
-       PTR_SUBU        t1, AT
-       .set            noat
-       jr              t1
-        PTR_ADDU       a0, t0                  /* dest ptr */
-
-       .set            push
-       .set            noreorder
-       .set            nomacro
-       f_fill64 a0, -64, a1, partial_fixup     /* ... but first do longs ... */
-2:     .set            pop
-       andi            a2, LONGMASK            /* At most one long to go */
-
-       beqz            a2, 1f
-        PTR_ADDU       a0, a2                  /* What's left */
-#ifdef __MIPSEB__
-       EX(sdr, a1, -1(a0), last_fixup)
-#endif
-#ifdef __MIPSEL__
-       EX(sdl, a1, -1(a0), last_fixup)
-#endif
-1:     jr              ra
-        move           a2, zero
-
-small_memset:
-       beqz            a2, 2f
-        PTR_ADDU       t1, a0, a2
-
-1:     PTR_ADDIU       a0, 1                   /* fill bytewise */
-       bne             t1, a0, 1b
-        sb             a1, -1(a0)
-
-2:     jr              ra                      /* done */
-        move           a2, zero
-       END(memset)
-
-first_fixup:
-       jr      ra
-        nop
-
-fwd_fixup:
-       PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
-       andi            a2, 0x3f
-       LONG_ADDU       a2, t1
-       jr              ra
-        LONG_SUBU      a2, t0
-
-partial_fixup:
-       PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
-       andi            a2, LONGMASK
-       LONG_ADDU       a2, t1
-       jr              ra
-        LONG_SUBU      a2, t0
-
-last_fixup:
-       jr              ra
-        andi           v1, a2, LONGMASK
index 989c900b8b14a5f4b3b1422552044fcd9ac24f52..5ad501b30b430f387f219c575d4f7fbe9c8c517e 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y  += csum_partial.o memcpy.o promlib.o \
+lib-y  += csum_partial.o memcpy.o memset.o promlib.o \
           strlen_user.o strncpy_user.o strnlen_user.o uncached.o
 
 obj-y  += iomap.o
similarity index 85%
rename from arch/mips/lib-32/memset.S
rename to arch/mips/lib/memset.S
index 1981485bd48b7f34120d0a70aa1fb4dcc74e5d3c..3f8b8b3d0b23575139ba263fb22a19eb301544f1 100644 (file)
 #include <asm/asm-offsets.h>
 #include <asm/regdef.h>
 
+#if LONGSIZE == 4
+#define LONG_S_L swl
+#define LONG_S_R swr
+#else
+#define LONG_S_L sdl
+#define LONG_S_R sdr
+#endif
+
 #define EX(insn,reg,addr,handler)                      \
 9:     insn    reg, addr;                              \
        .section __ex_table,"a";                        \
@@ -25,6 +33,7 @@
        EX(LONG_S, \val, (\offset +  5 * LONGSIZE)(\dst), \fixup)
        EX(LONG_S, \val, (\offset +  6 * LONGSIZE)(\dst), \fixup)
        EX(LONG_S, \val, (\offset +  7 * LONGSIZE)(\dst), \fixup)
+#if LONGSIZE == 4
        EX(LONG_S, \val, (\offset +  8 * LONGSIZE)(\dst), \fixup)
        EX(LONG_S, \val, (\offset +  9 * LONGSIZE)(\dst), \fixup)
        EX(LONG_S, \val, (\offset + 10 * LONGSIZE)(\dst), \fixup)
@@ -33,6 +42,7 @@
        EX(LONG_S, \val, (\offset + 13 * LONGSIZE)(\dst), \fixup)
        EX(LONG_S, \val, (\offset + 14 * LONGSIZE)(\dst), \fixup)
        EX(LONG_S, \val, (\offset + 15 * LONGSIZE)(\dst), \fixup)
+#endif
        .endm
 
 /*
@@ -49,9 +59,13 @@ LEAF(memset)
         move           v0, a0                  /* result */
 
        andi            a1, 0xff                /* spread fillword */
-       sll             t1, a1, 8
+       LONG_SLL                t1, a1, 8
        or              a1, t1
-       sll             t1, a1, 16
+       LONG_SLL                t1, a1, 16
+#if LONGSIZE == 8
+       or              a1, t1
+       LONG_SLL                t1, a1, 32
+#endif
        or              a1, t1
 1:
 
@@ -64,10 +78,10 @@ FEXPORT(__bzero)
         PTR_SUBU       t0, LONGSIZE            /* alignment in bytes */
 
 #ifdef __MIPSEB__
-       EX(swl, a1, (a0), first_fixup)          /* make word aligned */
+       EX(LONG_S_L, a1, (a0), first_fixup)     /* make word/dword aligned */
 #endif
 #ifdef __MIPSEL__
-       EX(swr, a1, (a0), first_fixup)          /* make word aligned */
+       EX(LONG_S_R, a1, (a0), first_fixup)     /* make word/dword aligned */
 #endif
        PTR_SUBU        a0, t0                  /* long align ptr */
        PTR_ADDU        a2, t0                  /* correct size */
@@ -75,7 +89,7 @@ FEXPORT(__bzero)
 1:     ori             t1, a2, 0x3f            /* # of full blocks */
        xori            t1, 0x3f
        beqz            t1, memset_partial      /* no block to fill */
-        andi           t0, a2, 0x3c
+        andi           t0, a2, 0x40-LONGSIZE
 
        PTR_ADDU        t1, a0                  /* end address */
        .set            reorder
@@ -86,7 +100,14 @@ FEXPORT(__bzero)
 
 memset_partial:
        PTR_LA          t1, 2f                  /* where to start */
+#if LONGSIZE == 4
        PTR_SUBU        t1, t0
+#else
+       .set            noat
+       LONG_SRL                AT, t0, 1
+       PTR_SUBU        t1, AT
+       .set            noat
+#endif
        jr              t1
         PTR_ADDU       a0, t0                  /* dest ptr */
 
@@ -100,10 +121,10 @@ memset_partial:
        beqz            a2, 1f
         PTR_ADDU       a0, a2                  /* What's left */
 #ifdef __MIPSEB__
-       EX(swr, a1, -1(a0), last_fixup)
+       EX(LONG_S_R, a1, -1(a0), last_fixup)
 #endif
 #ifdef __MIPSEL__
-       EX(swl, a1, -1(a0), last_fixup)
+       EX(LONG_S_L, a1, -1(a0), last_fixup)
 #endif
 1:     jr              ra
         move           a2, zero
index 98ce89f8068b9aa5c8ef6bbbf56cf42c9bca39a9..2388f7f3ffde9c2bffd45744f9f8adaacfd10048 100644 (file)
@@ -44,20 +44,24 @@ unsigned long __init run_uncached(void *func)
 
        if (sp >= (long)CKSEG0 && sp < (long)CKSEG2)
                usp = CKSEG1ADDR(sp);
+#ifdef CONFIG_64BIT
        else if ((long long)sp >= (long long)PHYS_TO_XKPHYS(0LL, 0) &&
                 (long long)sp < (long long)PHYS_TO_XKPHYS(8LL, 0))
                usp = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED,
                                     XKPHYS_TO_PHYS((long long)sp));
+#endif
        else {
                BUG();
                usp = sp;
        }
        if (lfunc >= (long)CKSEG0 && lfunc < (long)CKSEG2)
                ufunc = CKSEG1ADDR(lfunc);
+#ifdef CONFIG_64BIT
        else if ((long long)lfunc >= (long long)PHYS_TO_XKPHYS(0LL, 0) &&
                 (long long)lfunc < (long long)PHYS_TO_XKPHYS(8LL, 0))
                ufunc = PHYS_TO_XKPHYS((long long)K_CALG_UNCACHED,
                                       XKPHYS_TO_PHYS((long long)lfunc));
+#endif
        else {
                BUG();
                ufunc = lfunc;
index 43dba6ce6603be07de661fd6d80319b1bb5dc2fb..dfa0acbd7fc2b79eeee0bbd6dfefb29e9456592a 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/kernel.h>
 
 #include <asm/gdb-stub.h>
 #include <asm/io.h>
@@ -69,7 +70,7 @@ static void end_atlas_irq(unsigned int irq)
 }
 
 static struct irq_chip atlas_irq_type = {
-       .typename = "Atlas",
+       .name = "Atlas",
        .ack = disable_atlas_irq,
        .mask = disable_atlas_irq,
        .mask_ack = disable_atlas_irq,
@@ -220,7 +221,7 @@ msc_irqmap_t __initdata msc_irqmap[] = {
        {MSC01C_INT_TMR,                MSC01_IRQ_EDGE, 0},
        {MSC01C_INT_PCI,                MSC01_IRQ_LEVEL, 0},
 };
-int __initdata msc_nr_irqs = sizeof(msc_irqmap) / sizeof(*msc_irqmap);
+int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
 
 msc_irqmap_t __initdata msc_eicirqmap[] = {
        {MSC01E_INT_SW0,                MSC01_IRQ_LEVEL, 0},
@@ -231,14 +232,14 @@ msc_irqmap_t __initdata msc_eicirqmap[] = {
        {MSC01E_INT_PERFCTR,            MSC01_IRQ_LEVEL, 0},
        {MSC01E_INT_CPUCTR,             MSC01_IRQ_LEVEL, 0}
 };
-int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap) / sizeof(*msc_eicirqmap);
+int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
 
 void __init arch_init_irq(void)
 {
        init_atlas_irqs(ATLAS_INT_BASE);
 
        if (!cpu_has_veic)
-               mips_cpu_irq_init(MIPSCPU_INT_BASE);
+               mips_cpu_irq_init();
 
        switch(mips_revision_corid) {
        case MIPS_REVISION_CORID_CORE_MSC:
index eeed944e0f83eb9c0ba5c1b09ad3b760feaa040f..ebf0e16c5a0de5c36ff4c63016f42a9dbaf95328 100644 (file)
@@ -166,9 +166,8 @@ void __init prom_meminit(void)
        }
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       unsigned long freed = 0;
        unsigned long addr;
        int i;
 
@@ -176,17 +175,8 @@ unsigned long __init prom_free_prom_memory(void)
                if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
                        continue;
 
-               addr = PAGE_ALIGN(boot_mem_map.map[i].addr);
-               while (addr < boot_mem_map.map[i].addr
-                             + boot_mem_map.map[i].size) {
-                       ClearPageReserved(virt_to_page(__va(addr)));
-                       init_page_count(virt_to_page(__va(addr)));
-                       free_page((unsigned long)__va(addr));
-                       addr += PAGE_SIZE;
-                       freed += PAGE_SIZE;
-               }
+               addr = boot_mem_map.map[i].addr;
+               free_init_pages("prom memory",
+                               addr, addr + boot_mem_map.map[i].size);
        }
-       printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
-
-       return freed;
 }
index 90ad5bf3e2f175c8dd3c5ab055860ae988c3fdb2..3c206bb171602ff3ce331586ee63a11fc7319825 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/kernel.h>
 #include <linux/random.h>
 
 #include <asm/i8259.h>
@@ -289,7 +290,7 @@ msc_irqmap_t __initdata msc_irqmap[] = {
        {MSC01C_INT_TMR,                MSC01_IRQ_EDGE, 0},
        {MSC01C_INT_PCI,                MSC01_IRQ_LEVEL, 0},
 };
-int __initdata msc_nr_irqs = sizeof(msc_irqmap)/sizeof(msc_irqmap_t);
+int __initdata msc_nr_irqs = ARRAY_SIZE(msc_irqmap);
 
 msc_irqmap_t __initdata msc_eicirqmap[] = {
        {MSC01E_INT_SW0,                MSC01_IRQ_LEVEL, 0},
@@ -303,14 +304,14 @@ msc_irqmap_t __initdata msc_eicirqmap[] = {
        {MSC01E_INT_PERFCTR,            MSC01_IRQ_LEVEL, 0},
        {MSC01E_INT_CPUCTR,             MSC01_IRQ_LEVEL, 0}
 };
-int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap)/sizeof(msc_irqmap_t);
+int __initdata msc_nr_eicirqs = ARRAY_SIZE(msc_eicirqmap);
 
 void __init arch_init_irq(void)
 {
        init_i8259_irqs();
 
        if (!cpu_has_veic)
-               mips_cpu_irq_init (MIPSCPU_INT_BASE);
+               mips_cpu_irq_init();
 
         switch(mips_revision_corid) {
         case MIPS_REVISION_CORID_CORE_MSC:
index 874ccb0066b8aa7b6266ee8e377d16671d987408..c4b9de3a7f27ba922c3eda8e9f1a8713e5dc8f90 100644 (file)
@@ -113,5 +113,5 @@ asmlinkage void plat_irq_dispatch(void)
 
 void __init arch_init_irq(void)
 {
-       mips_cpu_irq_init(MIPSCPU_INT_BASE);
+       mips_cpu_irq_init();
 }
index 2ce449dce6f2401b7bb47542e6a5b8b8f31ff4a5..15ac0655c1ff49f59bf79564139e6ee32a182ddd 100644 (file)
@@ -21,9 +21,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <asm/mips-boards/simint.h>
-
-
-extern void mips_cpu_irq_init(int);
+#include <asm/irq_cpu.h>
 
 static inline int clz(unsigned long x)
 {
@@ -86,5 +84,5 @@ asmlinkage void plat_irq_dispatch(void)
 
 void __init arch_init_irq(void)
 {
-       mips_cpu_irq_init(MIPSCPU_INT_BASE);
+       mips_cpu_irq_init();
 }
index f7ce769833283b38c6af2ecc8c3c24dd1db6c352..46bc16f8b15d3fe4d50e3a9ab989a17f3e440114 100644 (file)
@@ -99,10 +99,9 @@ void __init prom_meminit(void)
        }
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
        int i;
-       unsigned long freed = 0;
        unsigned long addr;
 
        for (i = 0; i < boot_mem_map.nr_map; i++) {
@@ -110,16 +109,7 @@ unsigned long __init prom_free_prom_memory(void)
                        continue;
 
                addr = boot_mem_map.map[i].addr;
-               while (addr < boot_mem_map.map[i].addr
-                             + boot_mem_map.map[i].size) {
-                       ClearPageReserved(virt_to_page(__va(addr)));
-                       init_page_count(virt_to_page(__va(addr)));
-                       free_page((unsigned long)__va(addr));
-                       addr += PAGE_SIZE;
-                       freed += PAGE_SIZE;
-               }
+               free_init_pages("prom memory",
+                               addr, addr + boot_mem_map.map[i].size);
        }
-       printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
-
-       return freed;
 }
index 49065c133ebf4987d7f48666e90b0bac3076308c..125a4a85ec055988fad25f5ead85a48afd66e34c 100644 (file)
@@ -341,7 +341,6 @@ static int __init page_is_ram(unsigned long pagenr)
 void __init paging_init(void)
 {
        unsigned long zones_size[MAX_NR_ZONES] = { 0, };
-       unsigned long max_dma, low;
 #ifndef CONFIG_FLATMEM
        unsigned long zholes_size[MAX_NR_ZONES] = { 0, };
        unsigned long i, j, pfn;
@@ -354,19 +353,19 @@ void __init paging_init(void)
 #endif
        kmap_coherent_init();
 
-       max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-       low = max_low_pfn;
-
 #ifdef CONFIG_ISA
-       if (low < max_dma)
-               zones_size[ZONE_DMA] = low;
-       else {
-               zones_size[ZONE_DMA] = max_dma;
-               zones_size[ZONE_NORMAL] = low - max_dma;
-       }
-#else
-       zones_size[ZONE_DMA] = low;
+       if (max_low_pfn >= MAX_DMA_PFN)
+               if (min_low_pfn >= MAX_DMA_PFN) {
+                       zones_size[ZONE_DMA] = 0;
+                       zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn;
+               } else {
+                       zones_size[ZONE_DMA] = MAX_DMA_PFN - min_low_pfn;
+                       zones_size[ZONE_NORMAL] = max_low_pfn - MAX_DMA_PFN;
+               }
+       else
 #endif
+       zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn;
+
 #ifdef CONFIG_HIGHMEM
        zones_size[ZONE_HIGHMEM] = highend_pfn - highstart_pfn;
 
@@ -467,7 +466,7 @@ void __init mem_init(void)
 }
 #endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
-static void free_init_pages(char *what, unsigned long begin, unsigned long end)
+void free_init_pages(const char *what, unsigned long begin, unsigned long end)
 {
        unsigned long pfn;
 
@@ -493,18 +492,25 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 }
 #endif
 
-extern unsigned long prom_free_prom_memory(void);
-
 void free_initmem(void)
 {
-       unsigned long freed;
-
-       freed = prom_free_prom_memory();
-       if (freed)
-               printk(KERN_INFO "Freeing firmware memory: %ldkb freed\n",
-                      freed >> 10);
-
+       prom_free_prom_memory();
        free_init_pages("unused kernel memory",
                        __pa_symbol(&__init_begin),
                        __pa_symbol(&__init_end));
 }
+
+unsigned long pgd_current[NR_CPUS];
+/*
+ * On 64-bit we've got three-level pagetables with a slightly
+ * different layout ...
+ */
+#define __page_aligned(order) __attribute__((__aligned__(PAGE_SIZE<<order)))
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned(PGD_ORDER);
+#ifdef CONFIG_64BIT
+#ifdef MODULE_START
+pgd_t module_pg_dir[PTRS_PER_PGD] __page_aligned(PGD_ORDER);
+#endif
+pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned(PMD_ORDER);
+#endif
+pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned(PTE_ORDER);
index 67372f3f9654a3105e0b9d041d6c2650f848e240..2e8cebd49bc0b267c6edf6129c4f9ead814c98e3 100644 (file)
@@ -6,7 +6,7 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y += irq.o prom.o reset.o setup.o
+obj-y += irq.o platform.o prom.o reset.o setup.o
 
 obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
 obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
index 2efb25aa1aed10363fde84e3e5bb9a4c4bfd1476..f2b432585df245a70c84dddde8097e403ef137c6 100644 (file)
@@ -82,8 +82,8 @@ void __init arch_init_irq(void)
         */
        clear_c0_status(ST0_IM);
 
-       mips_cpu_irq_init(0);
-       rm7k_cpu_irq_init(8);
+       mips_cpu_irq_init();
+       rm7k_cpu_irq_init();
 
        /* set up the cascading interrupts */
        setup_irq(8, &cascade_mv64340);
index 6978654c712b80e8d1e85bcf7067eaa91c0b020d..022f6974b76eb505c369cf58eb246f99fa0e753a 100644 (file)
@@ -46,7 +46,9 @@
 
 extern unsigned long ja_fpga_base;
 
-#define JAGUAR_FPGA_WRITE(x,y) writeb(x, ja_fpga_base + JAGUAR_ATX_REG_##y)
-#define JAGUAR_FPGA_READ(x) readb(ja_fpga_base + JAGUAR_ATX_REG_##x)
+#define __FPGA_REG_TO_ADDR(reg)                                                \
+       ((void *) ja_fpga_base + JAGUAR_ATX_REG_##reg)
+#define JAGUAR_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
+#define JAGUAR_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
 
 #endif
diff --git a/arch/mips/momentum/jaguar_atx/platform.c b/arch/mips/momentum/jaguar_atx/platform.c
new file mode 100644 (file)
index 0000000..035ea51
--- /dev/null
@@ -0,0 +1,235 @@
+#include <linux/delay.h>
+#include <linux/if_ether.h>
+#include <linux/ioport.h>
+#include <linux/mv643xx.h>
+#include <linux/platform_device.h>
+
+#include "jaguar_atx_fpga.h"
+
+#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
+
+static struct resource mv643xx_eth_shared_resources[] = {
+       [0] = {
+               .name   = "ethernet shared base",
+               .start  = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
+               .end    = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
+                                      MV643XX_ETH_SHARED_REGS_SIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device mv643xx_eth_shared_device = {
+       .name           = MV643XX_ETH_SHARED_NAME,
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(mv643xx_eth_shared_resources),
+       .resource       = mv643xx_eth_shared_resources,
+};
+
+#define MV_SRAM_BASE                   0xfe000000UL
+#define MV_SRAM_SIZE                   (256 * 1024)
+
+#define MV_SRAM_RXRING_SIZE            (MV_SRAM_SIZE / 4)
+#define MV_SRAM_TXRING_SIZE            (MV_SRAM_SIZE / 4)
+
+#define MV_SRAM_BASE_ETH0              MV_SRAM_BASE
+#define MV_SRAM_BASE_ETH1              (MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
+
+#define MV64x60_IRQ_ETH_0 48
+#define MV64x60_IRQ_ETH_1 49
+#define MV64x60_IRQ_ETH_2 50
+
+#ifdef CONFIG_MV643XX_ETH_0
+
+static struct resource mv64x60_eth0_resources[] = {
+       [0] = {
+               .name   = "eth0 irq",
+               .start  = MV64x60_IRQ_ETH_0,
+               .end    = MV64x60_IRQ_ETH_0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static char eth0_mac_addr[ETH_ALEN];
+
+static struct mv643xx_eth_platform_data eth0_pd = {
+       .mac_addr       = eth0_mac_addr,
+
+       .tx_sram_addr   = MV_SRAM_BASE_ETH0,
+       .tx_sram_size   = MV_SRAM_TXRING_SIZE,
+       .tx_queue_size  = MV_SRAM_TXRING_SIZE / 16,
+
+       .rx_sram_addr   = MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
+       .rx_sram_size   = MV_SRAM_RXRING_SIZE,
+       .rx_queue_size  = MV_SRAM_RXRING_SIZE / 16,
+};
+
+static struct platform_device eth0_device = {
+       .name           = MV643XX_ETH_NAME,
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(mv64x60_eth0_resources),
+       .resource       = mv64x60_eth0_resources,
+       .dev = {
+               .platform_data = &eth0_pd,
+       },
+};
+#endif /* CONFIG_MV643XX_ETH_0 */
+
+#ifdef CONFIG_MV643XX_ETH_1
+
+static struct resource mv64x60_eth1_resources[] = {
+       [0] = {
+               .name   = "eth1 irq",
+               .start  = MV64x60_IRQ_ETH_1,
+               .end    = MV64x60_IRQ_ETH_1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static char eth1_mac_addr[ETH_ALEN];
+
+static struct mv643xx_eth_platform_data eth1_pd = {
+       .mac_addr       = eth1_mac_addr,
+
+       .tx_sram_addr   = MV_SRAM_BASE_ETH1,
+       .tx_sram_size   = MV_SRAM_TXRING_SIZE,
+       .tx_queue_size  = MV_SRAM_TXRING_SIZE / 16,
+
+       .rx_sram_addr   = MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
+       .rx_sram_size   = MV_SRAM_RXRING_SIZE,
+       .rx_queue_size  = MV_SRAM_RXRING_SIZE / 16,
+};
+
+static struct platform_device eth1_device = {
+       .name           = MV643XX_ETH_NAME,
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(mv64x60_eth1_resources),
+       .resource       = mv64x60_eth1_resources,
+       .dev = {
+               .platform_data = &eth1_pd,
+       },
+};
+#endif /* CONFIG_MV643XX_ETH_1 */
+
+#ifdef CONFIG_MV643XX_ETH_2
+
+static struct resource mv64x60_eth2_resources[] = {
+       [0] = {
+               .name   = "eth2 irq",
+               .start  = MV64x60_IRQ_ETH_2,
+               .end    = MV64x60_IRQ_ETH_2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static char eth2_mac_addr[ETH_ALEN];
+
+static struct mv643xx_eth_platform_data eth2_pd = {
+       .mac_addr       = eth2_mac_addr,
+};
+
+static struct platform_device eth2_device = {
+       .name           = MV643XX_ETH_NAME,
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(mv64x60_eth2_resources),
+       .resource       = mv64x60_eth2_resources,
+       .dev = {
+               .platform_data = &eth2_pd,
+       },
+};
+#endif /* CONFIG_MV643XX_ETH_2 */
+
+static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
+       &mv643xx_eth_shared_device,
+#ifdef CONFIG_MV643XX_ETH_0
+       &eth0_device,
+#endif
+#ifdef CONFIG_MV643XX_ETH_1
+       &eth1_device,
+#endif
+#ifdef CONFIG_MV643XX_ETH_2
+       &eth2_device,
+#endif
+};
+
+static u8 __init exchange_bit(u8 val, u8 cs)
+{
+       /* place the data */
+       JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
+       udelay(1);
+
+       /* turn the clock on */
+       JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
+       udelay(1);
+
+       /* turn the clock off and read-strobe */
+       JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
+
+       /* return the data */
+       return (JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
+}
+
+static void __init get_mac(char dest[6])
+{
+       u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+       int i,j;
+
+       for (i = 0; i < 12; i++)
+               exchange_bit(read_opcode[i], 1);
+
+       for (j = 0; j < 6; j++) {
+               dest[j] = 0;
+               for (i = 0; i < 8; i++) {
+                       dest[j] <<= 1;
+                       dest[j] |= exchange_bit(0, 1);
+               }
+       }
+
+       /* turn off CS */
+       exchange_bit(0,0);
+}
+
+/*
+ * Copy and increment ethernet MAC address by a small value.
+ *
+ * This is useful for systems where the only one MAC address is stored in
+ * non-volatile memory for multiple ports.
+ */
+static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
+       unsigned int add)
+{
+       int i;
+
+       BUG_ON(add >= 256);
+
+       for (i = ETH_ALEN; i >= 0; i--) {
+               dst[i] = src[i] + add;
+               add = dst[i] < src[i];          /* compute carry */
+       }
+
+       WARN_ON(add);
+}
+
+static int __init mv643xx_eth_add_pds(void)
+{
+       unsigned char mac[ETH_ALEN];
+       int ret;
+
+       get_mac(mac);
+#ifdef CONFIG_MV643XX_ETH_0
+       eth_mac_add(eth1_mac_addr, mac, 0);
+#endif
+#ifdef CONFIG_MV643XX_ETH_1
+       eth_mac_add(eth1_mac_addr, mac, 1);
+#endif
+#ifdef CONFIG_MV643XX_ETH_2
+       eth_mac_add(eth2_mac_addr, mac, 2);
+#endif
+       ret = platform_add_devices(mv643xx_eth_pd_devs,
+                       ARRAY_SIZE(mv643xx_eth_pd_devs));
+
+       return ret;
+}
+
+device_initcall(mv643xx_eth_add_pds);
+
+#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
index 3d2712929293e4de845fd36979eacaf0cf53df80..5dd154ee58f68306e666aee3fcb5b8e92847e63a 100644 (file)
@@ -39,56 +39,6 @@ const char *get_system_type(void)
        return "Momentum Jaguar-ATX";
 }
 
-#ifdef CONFIG_MV643XX_ETH
-extern unsigned char prom_mac_addr_base[6];
-
-static void burn_clocks(void)
-{
-       int i;
-
-       /* this loop should burn at least 1us -- this should be plenty */
-       for (i = 0; i < 0x10000; i++)
-               ;
-}
-
-static u8 exchange_bit(u8 val, u8 cs)
-{
-       /* place the data */
-       JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
-       burn_clocks();
-
-       /* turn the clock on */
-       JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
-       burn_clocks();
-
-       /* turn the clock off and read-strobe */
-       JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
-       /* return the data */
-       return ((JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1);
-}
-
-void get_mac(char dest[6])
-{
-       u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-       int i,j;
-
-       for (i = 0; i < 12; i++)
-               exchange_bit(read_opcode[i], 1);
-
-       for (j = 0; j < 6; j++) {
-               dest[j] = 0;
-               for (i = 0; i < 8; i++) {
-                       dest[j] <<= 1;
-                       dest[j] |= exchange_bit(0, 1);
-               }
-       }
-
-       /* turn off CS */
-       exchange_bit(0,0);
-}
-#endif
-
 #ifdef CONFIG_64BIT
 
 unsigned long signext(unsigned long addr)
@@ -228,16 +178,10 @@ void __init prom_init(void)
 #endif /* CONFIG_64BIT */
        mips_machgroup = MACH_GROUP_MOMENCO;
        mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
-
-#ifdef CONFIG_MV643XX_ETH
-       /* get the base MAC address for on-board ethernet ports */
-       get_mac(prom_mac_addr_base);
-#endif
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
index cea0e5deb80e78a38d95786f3b6a75e831715935..3862d1d1add443935dacfc62c768cf53e15240f2 100644 (file)
@@ -65,7 +65,7 @@ void __init arch_init_irq(void)
         */
        clear_c0_status(ST0_IM | ST0_BEV);
 
-       rm7k_cpu_irq_init(8);
+       rm7k_cpu_irq_init();
 
        /* set up the cascading interrupts */
        setup_irq(8, &cascade_mv64340);         /* unmask intControl IM8, IRQ 9 */
index 6ce9b7fdb824945e00d0b0c661fe783bd45a90fe..8e02df63578a6fd547fb0fd76c7626b4ecd418de 100644 (file)
@@ -180,9 +180,8 @@ void __init prom_init(void)
 #endif
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
index bb11fef08472b1b0b89a5d4ddb980ced32a3ac5a..186a140fd2a9af68e8302713b86bd6cff598c9a0 100644 (file)
@@ -84,7 +84,7 @@ void ll_cpci_irq(void)
 }
 
 struct irq_chip cpci_irq_type = {
-       .typename = "CPCI/FPGA",
+       .name = "CPCI/FPGA",
        .ack = mask_cpci_irq,
        .mask = mask_cpci_irq,
        .mask_ack = mask_cpci_irq,
index 2128684584f533a08b358793f5d45375b8f5e364..32d6fb4ee67955794547331adc8177e522d23784 100644 (file)
@@ -1,6 +1,4 @@
 
-#ifdef CONFIG_KGDB
-
 #include <asm/serial.h> /* For the serial port location and base baud */
 
 /* --- CONFIG --- */
@@ -121,5 +119,3 @@ int putDebugChar(uint8 byte)
        UART16550_WRITE(OFS_SEND_BUFFER, byte);
        return 1;
 }
-
-#endif
index ea65223a6d2c013a7d03252c5857b1f31b11325c..40472f7944d792cf3b69fbe72559db7cb5482108 100644 (file)
@@ -94,7 +94,7 @@ void __init arch_init_irq(void)
         */
        clear_c0_status(ST0_IM);
 
-       mips_cpu_irq_init(0);
+       mips_cpu_irq_init();
 
        /* set up the cascading interrupts */
        setup_irq(3, &cascade_fpga);
index d0b77e101d747cd0d0546de79746a523a9334d87..b689ceea8cfbf1b4244b61bd46321ac369184f92 100644 (file)
@@ -178,7 +178,6 @@ void __init prom_init(void)
 #endif
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
index a7a80c0da569653bb68169652e0c10a892b1d088..de1a31ee52f3458d166771457ef287a5eab16158 100644 (file)
@@ -77,7 +77,7 @@ void ll_uart_irq(void)
 }
 
 struct irq_chip uart_irq_type = {
-       .typename = "UART/FPGA",
+       .name = "UART/FPGA",
        .ack = mask_uart_irq,
        .mask = mask_uart_irq,
        .mask_ack = mask_uart_irq,
index 2128684584f533a08b358793f5d45375b8f5e364..32d6fb4ee67955794547331adc8177e522d23784 100644 (file)
@@ -1,6 +1,4 @@
 
-#ifdef CONFIG_KGDB
-
 #include <asm/serial.h> /* For the serial port location and base baud */
 
 /* --- CONFIG --- */
@@ -121,5 +119,3 @@ int putDebugChar(uint8 byte)
        UART16550_WRITE(OFS_SEND_BUFFER, byte);
        return 1;
 }
-
-#endif
index da46524e87cb50d4a8fe8a738231918096fce3b0..273541fe70871708d16f757e1f0b3b68f902973c 100644 (file)
@@ -94,8 +94,8 @@ void __init arch_init_irq(void)
        clear_c0_status(ST0_IM);
        local_irq_disable();
 
-       mips_cpu_irq_init(0);
-       rm7k_cpu_irq_init(8);
+       mips_cpu_irq_init();
+       rm7k_cpu_irq_init();
 
        gt64240_irq_init();
 }
index 2f75c6b91ec5211fc258a3b732232e4570864e65..836d0830720de9fa08043dc9f530e73a54e8e700 100644 (file)
@@ -79,7 +79,6 @@ void __init prom_init(void)
        }
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
index 55feaf798596fa1e0119f52bcd5f9831506fbb6e..ca395ef06d4e9514b82b4fdd41493199d7d1392f 100644 (file)
@@ -11,7 +11,7 @@ config PROFILING
 
 config OPROFILE
        tristate "OProfile system profiling (EXPERIMENTAL)"
-       depends on PROFILING && EXPERIMENTAL
+       depends on PROFILING && !!MIPS_MT_SMTC && EXPERIMENTAL
        help
          OProfile is a profiling system capable of profiling the
          whole system, include the kernel, kernel modules, libraries,
index 597b89764ba10e42a664a87e51d85bb367a30f09..a8d9d22b13dfffcd6178b151bf71d9ce2374478f 100644 (file)
  */
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/kernel.h>
 
 #include <asm/io.h>
+#include <asm/i8259.h>
 #include <asm/vr41xx/cmbvr4133.h>
 
 extern int vr4133_rockhopper;
@@ -142,7 +144,7 @@ int rockhopper_get_irq(struct pci_dev *dev, u8 pin, u8 slot)
        if (bus == NULL)
                return -1;
 
-       for (i = 0; i < sizeof (int_map) / sizeof (int_map[0]); i++) {
+       for (i = 0; i < ARRAY_SIZE(int_map); i++) {
                if (int_map[i].bus == bus->number && int_map[i].slot == slot) {
                        int line;
                        for (line = 0; line < 4; line++)
@@ -160,17 +162,7 @@ int rockhopper_get_irq(struct pci_dev *dev, u8 pin, u8 slot)
 #ifdef CONFIG_ROCKHOPPER
 void i8259_init(void)
 {
-       outb(0x11, 0x20);               /* Master ICW1 */
-       outb(I8259_IRQ_BASE, 0x21);     /* Master ICW2 */
-       outb(0x04, 0x21);               /* Master ICW3 */
-       outb(0x01, 0x21);               /* Master ICW4 */
-       outb(0xff, 0x21);               /* Master IMW */
-
-       outb(0x11, 0xa0);               /* Slave ICW1 */
-       outb(I8259_IRQ_BASE + 8, 0xa1); /* Slave ICW2 */
-       outb(0x02, 0xa1);               /* Slave ICW3 */
-       outb(0x01, 0xa1);               /* Slave ICW4 */
-       outb(0xff, 0xa1);               /* Slave IMW */
+       init_i8259_irqs();
 
        outb(0x00, 0x4d0);
        outb(0x02, 0x4d1);      /* USB IRQ9 is level */
index 2c36c108c4d62c7e0bff9029159e396a9089afa5..d48665ebd33c3249f7d865c01567a816acdf46fe 100644 (file)
@@ -159,7 +159,7 @@ int pnx8550_set_gic_priority(int irq, int priority)
 }
 
 static struct irq_chip level_irq_type = {
-       .typename =     "PNX Level IRQ",
+       .name =         "PNX Level IRQ",
        .ack =          mask_irq,
        .mask =         mask_irq,
        .mask_ack =     mask_irq,
index eb6ec11fef07b003303d4da27f822490140eef3a..8aeed6c2b8c36417b0ce84c9bf2420df6a5b7430 100644 (file)
@@ -106,9 +106,8 @@ int get_ethernet_addr(char *ethernet_addr)
        return 0;
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 extern int pnx8550_console_port;
index 0f659c9106ac21091872cd855a45c35a0a764677..6362c702e3890a6788878a7d70e6823f5fe17025 100644 (file)
@@ -93,7 +93,7 @@
  * Functions to READ and WRITE to serial port 1
  */
 #define        SERIAL_READ_1(ofs)              (*((volatile unsigned char*)    \
-                                       (TITAN_SERIAL_BASE_1 + ofs)
+                                       (TITAN_SERIAL_BASE_1 + ofs)))
 
 #define        SERIAL_WRITE_1(ofs, val)        ((*((volatile unsigned char*)   \
                                        (TITAN_SERIAL_BASE_1 + ofs))) = val)
index adb048527e7610d0e3dfc639c128f541e5a001ae..428d1f45a2872fc2289149ec1d4b0f1de1b17e31 100644 (file)
@@ -148,9 +148,9 @@ void __init arch_init_irq(void)
 {
        clear_c0_status(ST0_IM);
 
-       mips_cpu_irq_init(0);
-       rm7k_cpu_irq_init(8);
-       rm9k_cpu_irq_init(12);
+       mips_cpu_irq_init();
+       rm7k_cpu_irq_init();
+       rm9k_cpu_irq_init();
 
 #ifdef CONFIG_KGDB
        /* At this point, initialize the second serial port */
index 9fe4973377c315ad0dd829946c4521e8d7a1c3ac..1e1685e415a4504d0c94d9ea0470befdb42ccf82 100644 (file)
@@ -132,9 +132,8 @@ void __init prom_init(void)
        prom_grab_secondary();
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
index 1b9b0d396d3ed3e588bac9661fbb01316e21263d..6a6e15e400095cd0c3c42a920f1f64960f51d147 100644 (file)
@@ -171,6 +171,7 @@ static void __init py_map_ocd(void)
 
 static void __init py_uart_setup(void)
 {
+#ifdef CONFIG_SERIAL_8250
        struct uart_port up;
 
        /*
@@ -188,6 +189,7 @@ static void __init py_uart_setup(void)
 
        if (early_serial_setup(&up))
                printk(KERN_ERR "Early serial init of port 0 failed\n");
+#endif /* CONFIG_SERIAL_8250 */
 }
 
 static void __init py_rtc_setup(void)
index d174fac43031bf8a067502f8034c750d41c1e1c3..dae39b59de15e486069f75a42cf4d27da9857c75 100644 (file)
@@ -1,6 +1,5 @@
 #include <linux/init.h>
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0UL;
 }
index a1a9af6da7bf773fa28b28c6964b68b1931df457..6b6e97b90c6e56116548a71b0b8d75954877a2bb 100644 (file)
@@ -139,7 +139,7 @@ static void end_eisa1_irq(unsigned int irq)
 }
 
 static struct irq_chip ip22_eisa1_irq_type = {
-       .typename       = "IP22 EISA",
+       .name           = "IP22 EISA",
        .startup        = startup_eisa1_irq,
        .ack            = mask_and_ack_eisa1_irq,
        .mask           = disable_eisa1_irq,
@@ -194,7 +194,7 @@ static void end_eisa2_irq(unsigned int irq)
 }
 
 static struct irq_chip ip22_eisa2_irq_type = {
-       .typename       = "IP22 EISA",
+       .name           = "IP22 EISA",
        .startup        = startup_eisa2_irq,
        .ack            = mask_and_ack_eisa2_irq,
        .mask           = disable_eisa2_irq,
index c44f8be0644f43bf58d38cb744d2509724dac2ee..b454924aeb56c2f897b96c2cacfeefc643b9fca9 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <asm/mipsregs.h>
 #include <asm/addrspace.h>
+#include <asm/irq_cpu.h>
 
 #include <asm/sgi/ioc.h>
 #include <asm/sgi/hpc3.h>
@@ -52,7 +53,7 @@ static void disable_local0_irq(unsigned int irq)
 }
 
 static struct irq_chip ip22_local0_irq_type = {
-       .typename       = "IP22 local 0",
+       .name           = "IP22 local 0",
        .ack            = disable_local0_irq,
        .mask           = disable_local0_irq,
        .mask_ack       = disable_local0_irq,
@@ -73,7 +74,7 @@ void disable_local1_irq(unsigned int irq)
 }
 
 static struct irq_chip ip22_local1_irq_type = {
-       .typename       = "IP22 local 1",
+       .name           = "IP22 local 1",
        .ack            = disable_local1_irq,
        .mask           = disable_local1_irq,
        .mask_ack       = disable_local1_irq,
@@ -94,7 +95,7 @@ void disable_local2_irq(unsigned int irq)
 }
 
 static struct irq_chip ip22_local2_irq_type = {
-       .typename       = "IP22 local 2",
+       .name           = "IP22 local 2",
        .ack            = disable_local2_irq,
        .mask           = disable_local2_irq,
        .mask_ack       = disable_local2_irq,
@@ -115,7 +116,7 @@ void disable_local3_irq(unsigned int irq)
 }
 
 static struct irq_chip ip22_local3_irq_type = {
-       .typename       = "IP22 local 3",
+       .name           = "IP22 local 3",
        .ack            = disable_local3_irq,
        .mask           = disable_local3_irq,
        .mask_ack       = disable_local3_irq,
@@ -253,8 +254,6 @@ asmlinkage void plat_irq_dispatch(void)
                indy_8254timer_irq();
 }
 
-extern void mips_cpu_irq_init(unsigned int irq_base);
-
 void __init arch_init_irq(void)
 {
        int i;
@@ -316,7 +315,7 @@ void __init arch_init_irq(void)
        sgint->cmeimask1 = 0;
 
        /* init CPU irqs */
-       mips_cpu_irq_init(SGINT_CPU);
+       mips_cpu_irq_init();
 
        for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) {
                struct irq_chip *handler;
index b58bd522262b0ee5c231457b17408584143cae47..ddb6506d8341e2b2b14a404fc349254f549dbd17 100644 (file)
@@ -202,7 +202,6 @@ void __init sgimc_init(void)
 }
 
 void __init prom_meminit(void) {}
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
index 319f8803ef6f13b5dcf8536f469c2fd9784c4cbf..60ade7690e09861aafcfa0ca3f09da1eef8230a5 100644 (file)
@@ -333,7 +333,7 @@ static inline void disable_bridge_irq(unsigned int irq)
 }
 
 static struct irq_chip bridge_irq_type = {
-       .typename       = "bridge",
+       .name           = "bridge",
        .startup        = startup_bridge_irq,
        .shutdown       = shutdown_bridge_irq,
        .ack            = disable_bridge_irq,
index 16e5682b01f1d675687b8f6093a8c67b2ba62f18..0e3d535e9f4351f2ecabb097a1afb09ce7b4c41b 100644 (file)
@@ -498,10 +498,9 @@ void __init prom_meminit(void)
        }
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
        /* We got nothing to free here ...  */
-       return 0;
 }
 
 extern void pagetable_init(void);
index c20e9899b34b49fba2d95cdfa5688ea242287080..9ce513629b14543939c46321766ea9d6ae99429d 100644 (file)
@@ -181,7 +181,7 @@ static void disable_rt_irq(unsigned int irq)
 }
 
 static struct irq_chip rt_irq_type = {
-       .typename       = "SN HUB RT timer",
+       .name           = "SN HUB RT timer",
        .ack            = disable_rt_irq,
        .mask           = disable_rt_irq,
        .mask_ack       = disable_rt_irq,
index ae063864c0267be2e249867eb9456ad22381f7b7..8c450d9e8696fbbc0e413384da6ebbd483a1f256 100644 (file)
@@ -144,7 +144,7 @@ static void end_cpu_irq(unsigned int irq)
 }
 
 static struct irq_chip ip32_cpu_interrupt = {
-       .typename = "IP32 CPU",
+       .name = "IP32 CPU",
        .ack = disable_cpu_irq,
        .mask = disable_cpu_irq,
        .mask_ack = disable_cpu_irq,
@@ -193,7 +193,7 @@ static void end_crime_irq(unsigned int irq)
 }
 
 static struct irq_chip ip32_crime_interrupt = {
-       .typename = "IP32 CRIME",
+       .name = "IP32 CRIME",
        .ack = mask_and_ack_crime_irq,
        .mask = disable_crime_irq,
        .mask_ack = mask_and_ack_crime_irq,
@@ -234,7 +234,7 @@ static void end_macepci_irq(unsigned int irq)
 }
 
 static struct irq_chip ip32_macepci_interrupt = {
-       .typename = "IP32 MACE PCI",
+       .name = "IP32 MACE PCI",
        .ack = disable_macepci_irq,
        .mask = disable_macepci_irq,
        .mask_ack = disable_macepci_irq,
@@ -347,7 +347,7 @@ static void end_maceisa_irq(unsigned irq)
 }
 
 static struct irq_chip ip32_maceisa_interrupt = {
-       .typename = "IP32 MACE ISA",
+       .name = "IP32 MACE ISA",
        .ack = mask_and_ack_maceisa_irq,
        .mask = disable_maceisa_irq,
        .mask_ack = mask_and_ack_maceisa_irq,
@@ -379,7 +379,7 @@ static void end_mace_irq(unsigned int irq)
 }
 
 static struct irq_chip ip32_mace_interrupt = {
-       .typename = "IP32 MACE",
+       .name = "IP32 MACE",
        .ack = disable_mace_irq,
        .mask = disable_mace_irq,
        .mask_ack = disable_mace_irq,
index d37d40a3cdae8dc1a489d7c8bc1b37bd8bc71d1d..849d392a0013fbb0468362a3f85315d1ba4ae00c 100644 (file)
@@ -43,7 +43,6 @@ void __init prom_meminit (void)
 }
 
 
-unsigned long __init prom_free_prom_memory (void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
index 2e8f6b2e2420e8c7eb485ec575b7f14bf085d77c..1dc5d05d8962067fc9ef206ee019b2da90c0e6f5 100644 (file)
@@ -82,7 +82,7 @@ extern char sb1250_duart_present[];
 #endif
 
 static struct irq_chip bcm1480_irq_type = {
-       .typename = "BCM1480-IMR",
+       .name = "BCM1480-IMR",
        .ack = ack_bcm1480_irq,
        .mask = disable_bcm1480_irq,
        .mask_ack = ack_bcm1480_irq,
index 6e8952da6e2acf811541ea21873c83df229e9f4f..9e6099e6962266ed27023c9bdcbb59c32fa4b96c 100644 (file)
@@ -343,10 +343,9 @@ void __init prom_init(void)
        prom_meminit();
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
        /* Not sure what I'm supposed to do here.  Nothing, I think */
-       return 0;
 }
 
 void prom_putchar(char c)
index 82ce7533053f11ca017c5125bfd8c94b15b529b9..148239446e6e598c732111058847769b0388d5a4 100644 (file)
@@ -67,7 +67,7 @@ extern char sb1250_duart_present[];
 #endif
 
 static struct irq_chip sb1250_irq_type = {
-       .typename = "SB1250-IMR",
+       .name = "SB1250-IMR",
        .ack = ack_sb1250_irq,
        .mask = disable_sb1250_irq,
        .mask_ack = ack_sb1250_irq,
index 3c33a4517bc3ac72aba110fe3766f3b116c5b373..257c4e67435337e36f75daf7663603376381df58 100644 (file)
@@ -87,10 +87,9 @@ void __init prom_init(void)
        prom_meminit();
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
        /* Not sure what I'm supposed to do here.  Nothing, I think */
-       return 0;
 }
 
 void prom_putchar(char c)
index 8511bcc6d99df00450cf5ff56b1dc5b3b248e595..039e8e5405080b42613856346bd845ab25075657 100644 (file)
@@ -37,7 +37,7 @@ static void end_pciasic_irq(unsigned int irq)
 }
 
 static struct irq_chip pciasic_irq_type = {
-       .typename = "ASIC-PCI",
+       .name = "ASIC-PCI",
        .ack = disable_pciasic_irq,
        .mask = disable_pciasic_irq,
        .mask_ack = disable_pciasic_irq,
index d1d0f1f493b46d5c03f6a8f423c21ba773e524fb..1213d166f22eba023b273927fcbbbde91e6323ef 100644 (file)
@@ -67,9 +67,8 @@ void prom_printf(char *fmt, ...)
        va_end(args);
 }
 
-unsigned long prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 /*
index ed4a19adf36156dfff654ec8ec830ea10ad92120..e7f3e5b84dcffaa51f300f9ca7af141b8bca9b5c 100644 (file)
@@ -120,7 +120,7 @@ static void tx4927_irq_pic_disable(unsigned int irq);
 
 #define TX4927_CP0_NAME "TX4927-CP0"
 static struct irq_chip tx4927_irq_cp0_type = {
-       .typename       = TX4927_CP0_NAME,
+       .name           = TX4927_CP0_NAME,
        .ack            = tx4927_irq_cp0_disable,
        .mask           = tx4927_irq_cp0_disable,
        .mask_ack       = tx4927_irq_cp0_disable,
@@ -129,7 +129,7 @@ static struct irq_chip tx4927_irq_cp0_type = {
 
 #define TX4927_PIC_NAME "TX4927-PIC"
 static struct irq_chip tx4927_irq_pic_type = {
-       .typename       = TX4927_PIC_NAME,
+       .name           = TX4927_PIC_NAME,
        .ack            = tx4927_irq_pic_disable,
        .mask           = tx4927_irq_pic_disable,
        .mask_ack       = tx4927_irq_pic_disable,
index b54b529a29f9af209944eb2a77dc1aa916f53550..dcce88f403c9030145ac19577d25061305bfedad 100644 (file)
@@ -228,7 +228,7 @@ static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq);
 
 #define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
 static struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
-       .typename = TOSHIBA_RBTX4927_IOC_NAME,
+       .name = TOSHIBA_RBTX4927_IOC_NAME,
        .ack = toshiba_rbtx4927_irq_ioc_disable,
        .mask = toshiba_rbtx4927_irq_ioc_disable,
        .mask_ack = toshiba_rbtx4927_irq_ioc_disable,
@@ -241,7 +241,7 @@ static struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
 #ifdef CONFIG_TOSHIBA_FPCIB0
 #define TOSHIBA_RBTX4927_ISA_NAME "RBTX4927-ISA"
 static struct irq_chip toshiba_rbtx4927_irq_isa_type = {
-       .typename = TOSHIBA_RBTX4927_ISA_NAME,
+       .name = TOSHIBA_RBTX4927_ISA_NAME,
        .ack = toshiba_rbtx4927_irq_isa_mask_and_ack,
        .mask = toshiba_rbtx4927_irq_isa_disable,
        .mask_ack = toshiba_rbtx4927_irq_isa_mask_and_ack,
@@ -490,13 +490,13 @@ void toshiba_rbtx4927_irq_dump(char *key)
        {
                u32 i, j = 0;
                for (i = 0; i < NR_IRQS; i++) {
-                       if (strcmp(irq_desc[i].chip->typename, "none")
+                       if (strcmp(irq_desc[i].chip->name, "none")
                            == 0)
                                continue;
 
                        if ((i >= 1)
-                           && (irq_desc[i - 1].chip->typename ==
-                               irq_desc[i].chip->typename)) {
+                           && (irq_desc[i - 1].chip->name ==
+                               irq_desc[i].chip->name)) {
                                j++;
                        } else {
                                j = 0;
@@ -510,7 +510,7 @@ void toshiba_rbtx4927_irq_dump(char *key)
                             (u32) (irq_desc[i].action ? irq_desc[i].
                                    action->handler : 0),
                             irq_desc[i].depth,
-                            irq_desc[i].chip->typename, j);
+                            irq_desc[i].chip->name, j);
                }
        }
 #endif
index efe50562f0ce52a11b9c829feccb0781aa73708b..9a3a5babd1fb2facb0a78e3f14f584eaca654531 100644 (file)
@@ -80,9 +80,8 @@ void __init prom_init(void)
        add_memory_region(0, msize << 20, BOOT_MEM_RAM);
 }
 
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 const char *get_system_type(void)
index a347b424d91c76d9157c0f17a576576bc5242768..3a2dbfc2501459f77988429e01acdc68c2de624a 100644 (file)
@@ -49,7 +49,7 @@ static void tx4938_irq_pic_disable(unsigned int irq);
 
 #define TX4938_CP0_NAME "TX4938-CP0"
 static struct irq_chip tx4938_irq_cp0_type = {
-       .typename = TX4938_CP0_NAME,
+       .name = TX4938_CP0_NAME,
        .ack = tx4938_irq_cp0_disable,
        .mask = tx4938_irq_cp0_disable,
        .mask_ack = tx4938_irq_cp0_disable,
@@ -58,7 +58,7 @@ static struct irq_chip tx4938_irq_cp0_type = {
 
 #define TX4938_PIC_NAME "TX4938-PIC"
 static struct irq_chip tx4938_irq_pic_type = {
-       .typename = TX4938_PIC_NAME,
+       .name = TX4938_PIC_NAME,
        .ack = tx4938_irq_pic_disable,
        .mask = tx4938_irq_pic_disable,
        .mask_ack = tx4938_irq_pic_disable,
index b6f363d08011271deab6cb4405fd8084d1dc24cf..2e96dbb248b120f60fe02c7216b2f08e155764d2 100644 (file)
@@ -92,7 +92,7 @@ static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq);
 
 #define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
 static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
-       .typename = TOSHIBA_RBTX4938_IOC_NAME,
+       .name = TOSHIBA_RBTX4938_IOC_NAME,
        .ack = toshiba_rbtx4938_irq_ioc_disable,
        .mask = toshiba_rbtx4938_irq_ioc_disable,
        .mask_ack = toshiba_rbtx4938_irq_ioc_disable,
index e44daf30a7c1a84c0da46a0cb4bb083cddbc09a5..7dc6a0aae21cbec724cb8d867cfde287ad1f26b6 100644 (file)
@@ -56,9 +56,8 @@ void __init prom_init(void)
        return;
 }
 
-unsigned long  __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
 {
-       return 0;
 }
 
 void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
index c075261976c58df81ec4f4f1106b1c5bfe1c0739..adabc6bad440372815b0ded7fea23a6e5647a705 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
  *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-2005  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *  Copyright (C) 2003-2006  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
  *
  *  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
@@ -68,6 +68,7 @@ static unsigned char sysint2_assign[16] = {
 #define MPIUINTREG     0x0e
 #define MAIUINTREG     0x10
 #define MKIUINTREG     0x12
+#define MMACINTREG     0x12
 #define MGIUINTLREG    0x14
 #define MDSIUINTREG    0x16
 #define NMIREG         0x18
@@ -241,6 +242,30 @@ void vr41xx_disable_kiuint(uint16_t mask)
 
 EXPORT_SYMBOL(vr41xx_disable_kiuint);
 
+void vr41xx_enable_macint(uint16_t mask)
+{
+       struct irq_desc *desc = irq_desc + ETHERNET_IRQ;
+       unsigned long flags;
+
+       spin_lock_irqsave(&desc->lock, flags);
+       icu1_set(MMACINTREG, mask);
+       spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vr41xx_enable_macint);
+
+void vr41xx_disable_macint(uint16_t mask)
+{
+       struct irq_desc *desc = irq_desc + ETHERNET_IRQ;
+       unsigned long flags;
+
+       spin_lock_irqsave(&desc->lock, flags);
+       icu1_clear(MMACINTREG, mask);
+       spin_unlock_irqrestore(&desc->lock, flags);
+}
+
+EXPORT_SYMBOL(vr41xx_disable_macint);
+
 void vr41xx_enable_dsiuint(uint16_t mask)
 {
        struct irq_desc *desc = irq_desc + DSIU_IRQ;
@@ -428,7 +453,7 @@ static void enable_sysint1_irq(unsigned int irq)
 }
 
 static struct irq_chip sysint1_irq_type = {
-       .typename       = "SYSINT1",
+       .name           = "SYSINT1",
        .ack            = disable_sysint1_irq,
        .mask           = disable_sysint1_irq,
        .mask_ack       = disable_sysint1_irq,
@@ -446,7 +471,7 @@ static void enable_sysint2_irq(unsigned int irq)
 }
 
 static struct irq_chip sysint2_irq_type = {
-       .typename       = "SYSINT2",
+       .name           = "SYSINT2",
        .ack            = disable_sysint2_irq,
        .mask           = disable_sysint2_irq,
        .mask_ack       = disable_sysint2_irq,
index a2e285c1d4d5c85f8403199681fdb3b9ce08976a..4f97e0ba9e248ee00f4eb3101387277230be3c55 100644 (file)
@@ -81,7 +81,6 @@ void __init prom_init(void)
        }
 }
 
-unsigned long __init prom_free_prom_memory (void)
+void __init prom_free_prom_memory(void)
 {
-       return 0UL;
 }
index 16decf4ac2f406923535ab39172eb59900a38d67..cba36a247e32b634e21e0e03e2c39c27aa4342ea 100644 (file)
@@ -95,27 +95,27 @@ asmlinkage void plat_irq_dispatch(void)
        unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
 
        if (pending & CAUSEF_IP7)
-               do_IRQ(7);
+               do_IRQ(TIMER_IRQ);
        else if (pending & 0x7800) {
                if (pending & CAUSEF_IP3)
-                       irq_dispatch(3);
+                       irq_dispatch(INT1_IRQ);
                else if (pending & CAUSEF_IP4)
-                       irq_dispatch(4);
+                       irq_dispatch(INT2_IRQ);
                else if (pending & CAUSEF_IP5)
-                       irq_dispatch(5);
+                       irq_dispatch(INT3_IRQ);
                else if (pending & CAUSEF_IP6)
-                       irq_dispatch(6);
+                       irq_dispatch(INT4_IRQ);
        } else if (pending & CAUSEF_IP2)
-               irq_dispatch(2);
+               irq_dispatch(INT0_IRQ);
        else if (pending & CAUSEF_IP0)
-               do_IRQ(0);
+               do_IRQ(MIPS_SOFTINT0_IRQ);
        else if (pending & CAUSEF_IP1)
-               do_IRQ(1);
+               do_IRQ(MIPS_SOFTINT1_IRQ);
        else
                spurious_interrupt();
 }
 
 void __init arch_init_irq(void)
 {
-       mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
+       mips_cpu_irq_init();
 }
index 128ed8d6f1119d0ae995c8adc68b60a55ed61d2a..7d2d076b0f54f55e2ae5e77817ef0b77a62f6325 100644 (file)
 #include <linux/interrupt.h>
 
 #include <asm/io.h>
+#include <asm/i8259.h>
 #include <asm/vr41xx/cmbvr4133.h>
 
-extern void enable_8259A_irq(unsigned int irq);
-extern void disable_8259A_irq(unsigned int irq);
-extern void mask_and_ack_8259A(unsigned int irq);
-extern void init_8259A(int hoge);
-
 extern int vr4133_rockhopper;
 
-static void enable_i8259_irq(unsigned int irq)
-{
-       enable_8259A_irq(irq - I8259_IRQ_BASE);
-}
-
-static void disable_i8259_irq(unsigned int irq)
-{
-       disable_8259A_irq(irq - I8259_IRQ_BASE);
-}
-
-static void ack_i8259_irq(unsigned int irq)
-{
-       mask_and_ack_8259A(irq - I8259_IRQ_BASE);
-}
-
-static struct irq_chip i8259_irq_type = {
-       .typename       = "XT-PIC",
-       .ack            = ack_i8259_irq,
-       .mask           = disable_i8259_irq,
-       .mask_ack       = ack_i8259_irq,
-       .unmask         = enable_i8259_irq,
-};
-
 static int i8259_get_irq_number(int irq)
 {
-       unsigned long isr;
-
-       isr = inb(0x20);
-       irq = ffz(~isr);
-       if (irq == 2) {
-               isr = inb(0xa0);
-               irq = 8 + ffz(~isr);
-       }
-
-       if (irq < 0 || irq > 15)
-               return -EINVAL;
-
-       return I8259_IRQ_BASE + irq;
+       return i8259_irq();
 }
 
-static struct irqaction i8259_slave_cascade = {
-       .handler        = &no_action,
-       .name           = "cascade",
-};
-
 void __init rockhopper_init_irq(void)
 {
        int i;
@@ -84,11 +40,6 @@ void __init rockhopper_init_irq(void)
                return;
        }
 
-       for (i = I8259_IRQ_BASE; i <= I8259_IRQ_LAST; i++)
-               set_irq_chip_and_handler(i, &i8259_irq_type, handle_level_irq);
-
-       setup_irq(I8259_SLAVE_IRQ, &i8259_slave_cascade);
-
        vr41xx_set_irq_trigger(CMBVR41XX_INTC_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH);
        vr41xx_set_irq_level(CMBVR41XX_INTC_PIN, LEVEL_HIGH);
        vr41xx_cascade_irq(CMBVR41XX_INTC_IRQ, i8259_get_irq_number);
index 12272361c018c41b1b34c2f33a526e80646cc8b1..eaed402ad3460a758872ccf271971a36f6042add 100644 (file)
@@ -34,10 +34,6 @@ config GENERIC_HWEIGHT
        bool
        default y
 
-config GENERIC_CALIBRATE_DELAY
-       bool
-       default y
-
 config GENERIC_TIME
        def_bool y
 
@@ -134,6 +130,31 @@ config AUDIT_ARCH
        bool
        default y
 
+config S390_SWITCH_AMODE
+       bool "Switch kernel/user addressing modes"
+       help
+         This option allows to switch the addressing modes of kernel and user
+         space. The kernel parameter switch_amode=on will enable this feature,
+         default is disabled. Enabling this (via kernel parameter) on machines
+         earlier than IBM System z9-109 EC/BC will reduce system performance.
+
+         Note that this option will also be selected by selecting the execute
+         protection option below. Enabling the execute protection via the
+         noexec kernel parameter will also switch the addressing modes,
+         independent of the switch_amode kernel parameter.
+
+
+config S390_EXEC_PROTECT
+       bool "Data execute protection"
+       select S390_SWITCH_AMODE
+       help
+         This option allows to enable a buffer overflow protection for user
+         space programs and it also selects the addressing mode option above.
+         The kernel parameter noexec=on will enable this feature and also
+         switch the addressing modes, default is disabled. Enabling this (via
+         kernel parameter) on machines earlier than IBM System z9-109 EC/BC
+         will reduce system performance.
+
 comment "Code generation options"
 
 choice
index b8c2372902634c22db1f20162b966445ebf434a2..c9da7d16145e727f91f77b655016fa29fe5074ac 100644 (file)
@@ -81,7 +81,7 @@ static struct ctl_table appldata_dir_table[] = {
 /*
  * Timer
  */
-DEFINE_PER_CPU(struct vtimer_list, appldata_timer);
+static DEFINE_PER_CPU(struct vtimer_list, appldata_timer);
 static atomic_t appldata_expire_count = ATOMIC_INIT(0);
 
 static DEFINE_SPINLOCK(appldata_timer_lock);
index 8aea3698a77b84b466d56e3761370e083fa19461..4ca6157887025abaa19e6538408a8e8c12e7badb 100644 (file)
@@ -36,7 +36,7 @@
  * book:
  * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
  */
-struct appldata_mem_data {
+static struct appldata_mem_data {
        u64 timestamp;
        u32 sync_count_1;       /* after VM collected the record data, */
        u32 sync_count_2;       /* sync_count_1 and sync_count_2 should be the
index 075e619bf37dcdbbadb5bc9048a810c82924dc2d..f64b8c867ae2d3323128aa585d36b6a830911d1a 100644 (file)
@@ -34,7 +34,7 @@
  * book:
  * http://oss.software.ibm.com/developerworks/opensource/linux390/index.shtml
  */
-struct appldata_net_sum_data {
+static struct appldata_net_sum_data {
        u64 timestamp;
        u32 sync_count_1;       /* after VM collected the record data, */
        u32 sync_count_2;       /* sync_count_1 and sync_count_2 should be the
diff --git a/arch/s390/crypto/Kconfig b/arch/s390/crypto/Kconfig
new file mode 100644 (file)
index 0000000..99ff9f0
--- /dev/null
@@ -0,0 +1,60 @@
+config CRYPTO_SHA1_S390
+       tristate "SHA1 digest algorithm"
+       depends on S390
+       select CRYPTO_ALGAPI
+       help
+         This is the s390 hardware accelerated implementation of the
+         SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+
+config CRYPTO_SHA256_S390
+       tristate "SHA256 digest algorithm"
+       depends on S390
+       select CRYPTO_ALGAPI
+       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_DES_S390
+       tristate "DES and Triple DES cipher algorithms"
+       depends on S390
+       select CRYPTO_ALGAPI
+       select CRYPTO_BLKCIPHER
+       help
+         This us the s390 hardware accelerated implementation of the
+         DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
+
+config CRYPTO_AES_S390
+       tristate "AES cipher algorithms"
+       depends on S390
+       select CRYPTO_ALGAPI
+       select CRYPTO_BLKCIPHER
+       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 S390_PRNG
+       tristate "Pseudo random number generator device driver"
+       depends on S390
+       default "m"
+       help
+         Select this option if you want to use the s390 pseudo random number
+         generator. The PRNG is part of the cryptograhic processor functions
+         and uses triple-DES to generate secure random numbers like the
+         ANSI X9.17 standard. The PRNG is usable via the char device
+         /dev/prandom.
index bfe2541dc5cf125320020c5a78e36468107fbf03..14e552c5cc439a33ef93e3a7aec4ec96a147fe61 100644 (file)
@@ -6,5 +6,4 @@ 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_TEST) += crypt_s390_query.o
+obj-$(CONFIG_S390_PRNG) += prng.o
index 15c9eec02928ce0c68682624ccb146bb88d2081e..91636353f6f053d1986eb49a5089e68a78788388 100644 (file)
@@ -4,7 +4,7 @@
  * s390 implementation of the AES Cipher Algorithm.
  *
  * s390 Version:
- *   Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation
+ *   Copyright IBM Corp. 2005,2007
  *   Author(s): Jan Glauber (jang@de.ibm.com)
  *
  * Derived from "crypto/aes.c"
 /* 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;
+#define AES_KEYLEN_128         1
+#define AES_KEYLEN_192         2
+#define AES_KEYLEN_256         4
+
+static char keylen_flag = 0;
 
 struct s390_aes_ctx {
        u8 iv[AES_BLOCK_SIZE];
@@ -47,20 +49,19 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 
        switch (key_len) {
        case 16:
-               if (!has_aes_128)
+               if (!(keylen_flag & AES_KEYLEN_128))
                        goto fail;
                break;
        case 24:
-               if (!has_aes_192)
+               if (!(keylen_flag & AES_KEYLEN_192))
                        goto fail;
 
                break;
        case 32:
-               if (!has_aes_256)
+               if (!(keylen_flag & AES_KEYLEN_256))
                        goto fail;
                break;
        default:
-               /* invalid key length */
                goto fail;
                break;
        }
@@ -322,34 +323,32 @@ static int __init aes_init(void)
        int ret;
 
        if (crypt_s390_func_available(KM_AES_128_ENCRYPT))
-               has_aes_128 = 1;
+               keylen_flag |= AES_KEYLEN_128;
        if (crypt_s390_func_available(KM_AES_192_ENCRYPT))
-               has_aes_192 = 1;
+               keylen_flag |= AES_KEYLEN_192;
        if (crypt_s390_func_available(KM_AES_256_ENCRYPT))
-               has_aes_256 = 1;
+               keylen_flag |= AES_KEYLEN_256;
+
+       if (!keylen_flag)
+               return -EOPNOTSUPP;
 
-       if (!has_aes_128 && !has_aes_192 && !has_aes_256)
-               return -ENOSYS;
+       /* z9 109 and z9 BC/EC only support 128 bit key length */
+       if (keylen_flag == AES_KEYLEN_128)
+               printk(KERN_INFO
+                      "aes_s390: hardware acceleration only available for"
+                      "128 bit keys\n");
 
        ret = crypto_register_alg(&aes_alg);
-       if (ret != 0) {
-               printk(KERN_INFO "crypt_s390: aes-s390 couldn't be loaded.\n");
+       if (ret)
                goto aes_err;
-       }
 
        ret = crypto_register_alg(&ecb_aes_alg);
-       if (ret != 0) {
-               printk(KERN_INFO
-                      "crypt_s390: ecb-aes-s390 couldn't be loaded.\n");
+       if (ret)
                goto ecb_aes_err;
-       }
 
        ret = crypto_register_alg(&cbc_aes_alg);
-       if (ret != 0) {
-               printk(KERN_INFO
-                      "crypt_s390: cbc-aes-s390 couldn't be loaded.\n");
+       if (ret)
                goto cbc_aes_err;
-       }
 
 out:
        return ret;
index 2b137089f6251bbd920523770fa07821d25a79d1..2775d2618332d1a593e2aed4b3fb976b59a9d86a 100644 (file)
@@ -3,8 +3,9 @@
  *
  * Support for s390 cryptographic instructions.
  *
- *   Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
- *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *   Copyright IBM Corp. 2003,2007
+ *   Author(s): Thomas Spatzier
+ *             Jan Glauber (jan.glauber@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
@@ -32,7 +33,8 @@ enum crypt_s390_operations {
        CRYPT_S390_KMAC = 0x0500
 };
 
-/* function codes for KM (CIPHER MESSAGE) instruction
+/*
+ * function codes for KM (CIPHER MESSAGE) instruction
  * 0x80 is the decipher modifier bit
  */
 enum crypt_s390_km_func {
@@ -51,7 +53,8 @@ enum crypt_s390_km_func {
        KM_AES_256_DECRYPT  = CRYPT_S390_KM | 0x14 | 0x80,
 };
 
-/* function codes for KMC (CIPHER MESSAGE WITH CHAINING)
+/*
+ * function codes for KMC (CIPHER MESSAGE WITH CHAINING)
  * instruction
  */
 enum crypt_s390_kmc_func {
@@ -68,9 +71,11 @@ enum crypt_s390_kmc_func {
        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,
+       KMC_PRNG             = CRYPT_S390_KMC | 0x43,
 };
 
-/* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
+/*
+ * function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
  * instruction
  */
 enum crypt_s390_kimd_func {
@@ -79,7 +84,8 @@ enum crypt_s390_kimd_func {
        KIMD_SHA_256 = CRYPT_S390_KIMD | 2,
 };
 
-/* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST)
+/*
+ * function codes for KLMD (COMPUTE LAST MESSAGE DIGEST)
  * instruction
  */
 enum crypt_s390_klmd_func {
@@ -88,7 +94,8 @@ enum crypt_s390_klmd_func {
        KLMD_SHA_256 = CRYPT_S390_KLMD | 2,
 };
 
-/* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
+/*
+ * function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
  * instruction
  */
 enum crypt_s390_kmac_func {
@@ -98,229 +105,219 @@ enum crypt_s390_kmac_func {
        KMAC_TDEA_192 = CRYPT_S390_KMAC | 3
 };
 
-/* status word for s390 crypto instructions' QUERY functions */
-struct crypt_s390_query_status {
-       u64 high;
-       u64 low;
-};
-
-/*
+/**
+ * crypt_s390_km:
+ * @func: the function code passed to KM; see crypt_s390_km_func
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
  * Executes the KM (CIPHER MESSAGE) operation of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_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
- * @param src_len: length of src operand in bytes
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- *     for encryption/decryption funcs
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for encryption/decryption funcs
  */
-static inline int
-crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len)
+static inline int crypt_s390_km(long func, void *param,
+                               u8 *dest, const u8 *src, long src_len)
 {
        register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-       register void__param asm("1") = param;
-       register const u8__src asm("2") = src;
+       register void *__param asm("1") = param;
+       register const u8 *__src asm("2") = src;
        register long __src_len asm("3") = src_len;
-       register u8__dest asm("4") = dest;
+       register u8 *__dest asm("4") = dest;
        int ret;
 
        asm volatile(
                "0:     .insn   rre,0xb92e0000,%3,%1 \n" /* KM opcode */
                "1:     brc     1,0b \n" /* handle partial completion */
-               "       ahi     %0,%h7\n"
-               "2:     ahi     %0,%h8\n"
-               "3:\n"
-               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               "       la      %0,0\n"
+               "2:\n"
+               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
-               : "d" (__func), "a" (__param), "0" (-EFAULT),
-                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+               : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
                return ret;
        return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
-/*
+/**
+ * crypt_s390_kmc:
+ * @func: the function code passed to KM; see crypt_s390_kmc_func
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
  * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_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
- * @param src_len: length of src operand in bytes
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- *     for encryption/decryption funcs
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for encryption/decryption funcs
  */
-static inline int
-crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
+static inline int crypt_s390_kmc(long func, void *param,
+                                u8 *dest, const u8 *src, long src_len)
 {
        register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-       register void__param asm("1") = param;
-       register const u8__src asm("2") = src;
+       register void *__param asm("1") = param;
+       register const u8 *__src asm("2") = src;
        register long __src_len asm("3") = src_len;
-       register u8__dest asm("4") = dest;
+       register u8 *__dest asm("4") = dest;
        int ret;
 
        asm volatile(
                "0:     .insn   rre,0xb92f0000,%3,%1 \n" /* KMC opcode */
                "1:     brc     1,0b \n" /* handle partial completion */
-               "       ahi     %0,%h7\n"
-               "2:     ahi     %0,%h8\n"
-               "3:\n"
-               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               "       la      %0,0\n"
+               "2:\n"
+               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len), "+a" (__dest)
-               : "d" (__func), "a" (__param), "0" (-EFAULT),
-                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+               : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
                return ret;
        return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
-/*
+/**
+ * crypt_s390_kimd:
+ * @func: the function code passed to KM; see crypt_s390_kimd_func
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
  * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation
  * of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_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
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- *     for digest funcs
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for digest funcs
  */
-static inline int
-crypt_s390_kimd(long func, void* param, const u8* src, long src_len)
+static inline int crypt_s390_kimd(long func, void *param,
+                                 const u8 *src, long src_len)
 {
        register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-       register void__param asm("1") = param;
-       register const u8__src asm("2") = src;
+       register void *__param asm("1") = param;
+       register const u8 *__src asm("2") = src;
        register long __src_len asm("3") = src_len;
        int ret;
 
        asm volatile(
                "0:     .insn   rre,0xb93e0000,%1,%1 \n" /* KIMD opcode */
                "1:     brc     1,0b \n" /* handle partial completion */
-               "       ahi     %0,%h6\n"
-               "2:     ahi     %0,%h7\n"
-               "3:\n"
-               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               "       la      %0,0\n"
+               "2:\n"
+               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len)
-               : "d" (__func), "a" (__param), "0" (-EFAULT),
-                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+               : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
                return ret;
        return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
-/*
+/**
+ * crypt_s390_klmd:
+ * @func: the function code passed to KM; see crypt_s390_klmd_func
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
  * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_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
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- *     for digest funcs
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for digest funcs
  */
-static inline int
-crypt_s390_klmd(long func, void* param, const u8* src, long src_len)
+static inline int crypt_s390_klmd(long func, void *param,
+                                 const u8 *src, long src_len)
 {
        register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-       register void__param asm("1") = param;
-       register const u8__src asm("2") = src;
+       register void *__param asm("1") = param;
+       register const u8 *__src asm("2") = src;
        register long __src_len asm("3") = src_len;
        int ret;
 
        asm volatile(
                "0:     .insn   rre,0xb93f0000,%1,%1 \n" /* KLMD opcode */
                "1:     brc     1,0b \n" /* handle partial completion */
-               "       ahi     %0,%h6\n"
-               "2:     ahi     %0,%h7\n"
-               "3:\n"
-               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               "       la      %0,0\n"
+               "2:\n"
+               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len)
-               : "d" (__func), "a" (__param), "0" (-EFAULT),
-                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+               : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
                return ret;
        return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
-/*
+/**
+ * crypt_s390_kmac:
+ * @func: the function code passed to KM; see crypt_s390_klmd_func
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
  * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation
  * of the CPU.
- * @param func: the function code passed to KM; see crypt_s390_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
- * @returns < zero for failure, 0 for the query func, number of processed bytes
- *     for digest funcs
+ *
+ * Returns -1 for failure, 0 for the query func, number of processed
+ * bytes for digest funcs
  */
-static inline int
-crypt_s390_kmac(long func, void* param, const u8* src, long src_len)
+static inline int crypt_s390_kmac(long func, void *param,
+                                 const u8 *src, long src_len)
 {
        register long __func asm("0") = func & CRYPT_S390_FUNC_MASK;
-       register void__param asm("1") = param;
-       register const u8__src asm("2") = src;
+       register void *__param asm("1") = param;
+       register const u8 *__src asm("2") = src;
        register long __src_len asm("3") = src_len;
        int ret;
 
        asm volatile(
                "0:     .insn   rre,0xb91e0000,%1,%1 \n" /* KLAC opcode */
                "1:     brc     1,0b \n" /* handle partial completion */
-               "       ahi     %0,%h6\n"
-               "2:     ahi     %0,%h7\n"
-               "3:\n"
-               EX_TABLE(0b,3b) EX_TABLE(1b,2b)
+               "       la      %0,0\n"
+               "2:\n"
+               EX_TABLE(0b,2b) EX_TABLE(1b,2b)
                : "=d" (ret), "+a" (__src), "+d" (__src_len)
-               : "d" (__func), "a" (__param), "0" (-EFAULT),
-                 "K" (ENOSYS), "K" (-ENOSYS + EFAULT) : "cc", "memory");
+               : "d" (__func), "a" (__param), "0" (-1) : "cc", "memory");
        if (ret < 0)
                return ret;
        return (func & CRYPT_S390_FUNC_MASK) ? src_len - __src_len : __src_len;
 }
 
 /**
+ * crypt_s390_func_available:
+ * @func: the function code of the specific function; 0 if op in general
+ *
  * Tests if a specific 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
+ *
+ * Returns 1 if func available; 0 if func or op in general not available
  */
-static inline int
-crypt_s390_func_available(int func)
+static inline int crypt_s390_func_available(int func)
 {
+       unsigned char status[16];
        int ret;
 
-       struct crypt_s390_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);
-                       break;
-               case CRYPT_S390_KMC:
-                       ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0);
-                       break;
-               case CRYPT_S390_KIMD:
-                       ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0);
-                       break;
-               case CRYPT_S390_KLMD:
-                       ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0);
-                       break;
-               case CRYPT_S390_KMAC:
-                       ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
-                       break;
-               default:
-                       ret = 0;
-                       return ret;
-       }
-       if (ret >= 0){
-               func &= CRYPT_S390_FUNC_MASK;
-               func &= 0x7f; //mask modifier bit
-               if (func < 64){
-                       ret = (status.high >> (64 - func - 1)) & 0x1;
-               } else {
-                       ret = (status.low >> (128 - func - 1)) & 0x1;
-               }
-       } else {
-               ret = 0;
+       switch (func & CRYPT_S390_OP_MASK) {
+       case CRYPT_S390_KM:
+               ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
+               break;
+       case CRYPT_S390_KMC:
+               ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0);
+               break;
+       case CRYPT_S390_KIMD:
+               ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0);
+               break;
+       case CRYPT_S390_KLMD:
+               ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0);
+               break;
+       case CRYPT_S390_KMAC:
+               ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0);
+               break;
+       default:
+               return 0;
        }
-       return ret;
+       if (ret < 0)
+               return 0;
+       func &= CRYPT_S390_FUNC_MASK;
+       func &= 0x7f;           /* mask modifier bit */
+       return (status[func >> 3] & (0x80 >> (func & 7))) != 0;
 }
 
-#endif // _CRYPTO_ARCH_S390_CRYPT_S390_H
+#endif /* _CRYPTO_ARCH_S390_CRYPT_S390_H */
diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c
deleted file mode 100644 (file)
index 54fb11d..0000000
+++ /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 <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <asm/errno.h>
-#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 functions */
-       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");
index e3f5c5f238fe53dd34a4102e954a95b135b6f6d5..5706af266442700fa218c9105cdae81ef0d71e69 100644 (file)
@@ -10,8 +10,9 @@
  * scatterlist interface.  Changed LGPL to GPL per section 3 of the LGPL.
  *
  * s390 Version:
- *   Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
- *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *   Copyright IBM Corp. 2003
+ *   Author(s): Thomas Spatzier
+ *             Jan Glauber (jan.glauber@de.ibm.com)
  *
  * Derived from "crypto/des.c"
  *   Copyright (c) 1992 Dana L. How.
@@ -30,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/crypto.h>
+#include "crypto_des.h"
 
 #define ROR(d,c,o)     ((d) = (d) >> (c) | (d) << (o))
 
index 2aba04852fe3ebb1b75b4faf58d3b6317396c734..ea22707f435f440d1974d1ff586b3247871c0266 100644 (file)
@@ -3,9 +3,9 @@
  *
  * s390 implementation of the DES Cipher Algorithm.
  *
- * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Thomas Spatzier (tspat@de.ibm.com)
- *
+ * Copyright IBM Corp. 2003,2007
+ * Author(s): Thomas Spatzier
+ *           Jan Glauber (jan.glauber@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
@@ -557,7 +557,7 @@ static int init(void)
        if (!crypt_s390_func_available(KM_DEA_ENCRYPT) ||
            !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) ||
            !crypt_s390_func_available(KM_TDEA_192_ENCRYPT))
-               return -ENOSYS;
+               return -EOPNOTSUPP;
 
        ret = crypto_register_alg(&des_alg);
        if (ret)
diff --git a/arch/s390/crypto/prng.c b/arch/s390/crypto/prng.c
new file mode 100644 (file)
index 0000000..8eb3a1a
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright IBM Corp. 2006,2007
+ * Author(s): Jan Glauber <jan.glauber@de.ibm.com>
+ * Driver for the s390 pseudo random number generator
+ */
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/random.h>
+#include <asm/debug.h>
+#include <asm/uaccess.h>
+
+#include "crypt_s390.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jan Glauber <jan.glauber@de.ibm.com>");
+MODULE_DESCRIPTION("s390 PRNG interface");
+
+static int prng_chunk_size = 256;
+module_param(prng_chunk_size, int, S_IRUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(prng_chunk_size, "PRNG read chunk size in bytes");
+
+static int prng_entropy_limit = 4096;
+module_param(prng_entropy_limit, int, S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
+MODULE_PARM_DESC(prng_entropy_limit,
+       "PRNG add entropy after that much bytes were produced");
+
+/*
+ * Any one who considers arithmetical methods of producing random digits is,
+ * of course, in a state of sin. -- John von Neumann
+ */
+
+struct s390_prng_data {
+       unsigned long count; /* how many bytes were produced */
+       char *buf;
+};
+
+static struct s390_prng_data *p;
+
+/* copied from libica, use a non-zero initial parameter block */
+static unsigned char parm_block[32] = {
+0x0F,0x2B,0x8E,0x63,0x8C,0x8E,0xD2,0x52,0x64,0xB7,0xA0,0x7B,0x75,0x28,0xB8,0xF4,
+0x75,0x5F,0xD2,0xA6,0x8D,0x97,0x11,0xFF,0x49,0xD8,0x23,0xF3,0x7E,0x21,0xEC,0xA0,
+};
+
+static int prng_open(struct inode *inode, struct file *file)
+{
+       return nonseekable_open(inode, file);
+}
+
+static void prng_add_entropy(void)
+{
+       __u64 entropy[4];
+       unsigned int i;
+       int ret;
+
+       for (i = 0; i < 16; i++) {
+               ret = crypt_s390_kmc(KMC_PRNG, parm_block, (char *)entropy,
+                                    (char *)entropy, sizeof(entropy));
+               BUG_ON(ret < 0 || ret != sizeof(entropy));
+               memcpy(parm_block, entropy, sizeof(entropy));
+       }
+}
+
+static void prng_seed(int nbytes)
+{
+       char buf[16];
+       int i = 0;
+
+       BUG_ON(nbytes > 16);
+       get_random_bytes(buf, nbytes);
+
+       /* Add the entropy */
+       while (nbytes >= 8) {
+               *((__u64 *)parm_block) ^= *((__u64 *)buf+i*8);
+               prng_add_entropy();
+               i += 8;
+               nbytes -= 8;
+       }
+       prng_add_entropy();
+}
+
+static ssize_t prng_read(struct file *file, char __user *ubuf, size_t nbytes,
+                        loff_t *ppos)
+{
+       int chunk, n;
+       int ret = 0;
+       int tmp;
+
+       /* nbytes can be arbitrary long, we spilt it into chunks */
+       while (nbytes) {
+               /* same as in extract_entropy_user in random.c */
+               if (need_resched()) {
+                       if (signal_pending(current)) {
+                               if (ret == 0)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
+                       schedule();
+               }
+
+               /*
+                * we lose some random bytes if an attacker issues
+                * reads < 8 bytes, but we don't care
+                */
+               chunk = min_t(int, nbytes, prng_chunk_size);
+
+               /* PRNG only likes multiples of 8 bytes */
+               n = (chunk + 7) & -8;
+
+               if (p->count > prng_entropy_limit)
+                       prng_seed(8);
+
+               /* if the CPU supports PRNG stckf is present too */
+               asm volatile(".insn     s,0xb27c0000,%0"
+                            : "=m" (*((unsigned long long *)p->buf)) : : "cc");
+
+               /*
+                * Beside the STCKF the input for the TDES-EDE is the output
+                * of the last operation. We differ here from X9.17 since we
+                * only store one timestamp into the buffer. Padding the whole
+                * buffer with timestamps does not improve security, since
+                * successive stckf have nearly constant offsets.
+                * If an attacker knows the first timestamp it would be
+                * trivial to guess the additional values. One timestamp
+                * is therefore enough and still guarantees unique input values.
+                *
+                * Note: you can still get strict X9.17 conformity by setting
+                * prng_chunk_size to 8 bytes.
+               */
+               tmp = crypt_s390_kmc(KMC_PRNG, parm_block, p->buf, p->buf, n);
+               BUG_ON((tmp < 0) || (tmp != n));
+
+               p->count += n;
+
+               if (copy_to_user(ubuf, p->buf, chunk))
+                       return -EFAULT;
+
+               nbytes -= chunk;
+               ret += chunk;
+               ubuf += chunk;
+       }
+       return ret;
+}
+
+static struct file_operations prng_fops = {
+       .owner          = THIS_MODULE,
+       .open           = &prng_open,
+       .release        = NULL,
+       .read           = &prng_read,
+};
+
+static struct miscdevice prng_dev = {
+       .name   = "prandom",
+       .minor  = MISC_DYNAMIC_MINOR,
+       .fops   = &prng_fops,
+};
+
+static int __init prng_init(void)
+{
+       int ret;
+
+       /* check if the CPU has a PRNG */
+       if (!crypt_s390_func_available(KMC_PRNG))
+               return -EOPNOTSUPP;
+
+       if (prng_chunk_size < 8)
+               return -EINVAL;
+
+       p = kmalloc(sizeof(struct s390_prng_data), GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
+       p->count = 0;
+
+       p->buf = kmalloc(prng_chunk_size, GFP_KERNEL);
+       if (!p->buf) {
+               ret = -ENOMEM;
+               goto out_free;
+       }
+
+       /* initialize the PRNG, add 128 bits of entropy */
+       prng_seed(16);
+
+       ret = misc_register(&prng_dev);
+       if (ret) {
+               printk(KERN_WARNING
+                      "Could not register misc device for PRNG.\n");
+               goto out_buf;
+       }
+       return 0;
+
+out_buf:
+       kfree(p->buf);
+out_free:
+       kfree(p);
+       return ret;
+}
+
+static void __exit prng_exit(void)
+{
+       /* wipe me */
+       memset(p->buf, 0, prng_chunk_size);
+       kfree(p->buf);
+       kfree(p);
+
+       misc_deregister(&prng_dev);
+}
+
+module_init(prng_init);
+module_exit(prng_exit);
index 49ca8690ee39b7d53e116274b74bd883698a2e01..969639f31977dd7b235d66e434bb6234d23f0539 100644 (file)
@@ -8,8 +8,9 @@
  * implementation written by Steve Reid.
  *
  * s390 Version:
- *   Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation
- *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *   Copyright IBM Corp. 2003,2007
+ *   Author(s): Thomas Spatzier
+ *             Jan Glauber (jan.glauber@de.ibm.com)
  *
  * Derived from "crypto/sha1.c"
  *   Copyright (c) Alan Smithee.
@@ -43,16 +44,14 @@ struct crypt_s390_sha1_ctx {
 static void sha1_init(struct crypto_tfm *tfm)
 {
        struct crypt_s390_sha1_ctx *ctx = crypto_tfm_ctx(tfm);
-       static const u32 initstate[5] = {
-               0x67452301,
-               0xEFCDAB89,
-               0x98BADCFE,
-               0x10325476,
-               0xC3D2E1F0
-       };
+
+       ctx->state[0] = 0x67452301;
+       ctx->state[1] = 0xEFCDAB89;
+       ctx->state[2] = 0x98BADCFE;
+       ctx->state[3] = 0x10325476;
+       ctx->state[4] = 0xC3D2E1F0;
 
        ctx->count = 0;
-       memcpy(ctx->state, &initstate, sizeof(initstate));
        ctx->buf_len = 0;
 }
 
@@ -63,13 +62,13 @@ static void sha1_update(struct crypto_tfm *tfm, const u8 *data,
        long imd_len;
 
        sctx = crypto_tfm_ctx(tfm);
-       sctx->count += len * 8; //message bit length
+       sctx->count += len * 8; /* message bit length */
 
-       //anything in buffer yet? -> must be completed
+       /* anything in buffer yet? -> must be completed */
        if (sctx->buf_len && (sctx->buf_len + len) >= SHA1_BLOCK_SIZE) {
-               //complete full block and hash
+               /* complete full block and hash */
                memcpy(sctx->buffer + sctx->buf_len, data,
-                               SHA1_BLOCK_SIZE - sctx->buf_len);
+                      SHA1_BLOCK_SIZE - sctx->buf_len);
                crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer,
                                SHA1_BLOCK_SIZE);
                data += SHA1_BLOCK_SIZE - sctx->buf_len;
@@ -77,37 +76,36 @@ static void sha1_update(struct crypto_tfm *tfm, const u8 *data,
                sctx->buf_len = 0;
        }
 
-       //rest of data contains full blocks?
+       /* rest of data contains full blocks? */
        imd_len = len & ~0x3ful;
-       if (imd_len){
+       if (imd_len) {
                crypt_s390_kimd(KIMD_SHA_1, sctx->state, data, imd_len);
                data += imd_len;
                len -= imd_len;
        }
-       //anything left? store in buffer
-       if (len){
+       /* anything left? store in buffer */
+       if (len) {
                memcpy(sctx->buffer + sctx->buf_len , data, len);
                sctx->buf_len += len;
        }
 }
 
 
-static void
-pad_message(struct crypt_s390_sha1_ctx* sctx)
+static void pad_message(struct crypt_s390_sha1_ctx* sctx)
 {
        int index;
 
        index = sctx->buf_len;
-       sctx->buf_len = (sctx->buf_len < 56)?
-               SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE;
-       //start pad with 1
+       sctx->buf_len = (sctx->buf_len < 56) ?
+                        SHA1_BLOCK_SIZE:2 * SHA1_BLOCK_SIZE;
+       /* start pad with 1 */
        sctx->buffer[index] = 0x80;
-       //pad with zeros
+       /* pad with zeros */
        index++;
        memset(sctx->buffer + index, 0x00, sctx->buf_len - index);
-       //append length
+       /* append length */
        memcpy(sctx->buffer + sctx->buf_len - 8, &sctx->count,
-                       sizeof sctx->count);
+              sizeof sctx->count);
 }
 
 /* Add padding and return the message digest. */
@@ -115,47 +113,40 @@ static void sha1_final(struct crypto_tfm *tfm, u8 *out)
 {
        struct crypt_s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
 
-       //must perform manual padding
+       /* must perform manual padding */
        pad_message(sctx);
        crypt_s390_kimd(KIMD_SHA_1, sctx->state, sctx->buffer, sctx->buf_len);
-       //copy digest to out
+       /* copy digest to out */
        memcpy(out, sctx->state, SHA1_DIGEST_SIZE);
-       /* Wipe context */
+       /* wipe context */
        memset(sctx, 0, sizeof *sctx);
 }
 
 static struct crypto_alg alg = {
        .cra_name       =       "sha1",
-       .cra_driver_name =      "sha1-s390",
+       .cra_driver_name      "sha1-s390",
        .cra_priority   =       CRYPT_S390_PRIORITY,
        .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
        .cra_blocksize  =       SHA1_BLOCK_SIZE,
        .cra_ctxsize    =       sizeof(struct crypt_s390_sha1_ctx),
        .cra_module     =       THIS_MODULE,
-       .cra_list       =       LIST_HEAD_INIT(alg.cra_list),
+       .cra_list       =       LIST_HEAD_INIT(alg.cra_list),
        .cra_u          =       { .digest = {
        .dia_digestsize =       SHA1_DIGEST_SIZE,
-       .dia_init       =       sha1_init,
-       .dia_update     =       sha1_update,
-       .dia_final      =       sha1_final } }
+       .dia_init       =       sha1_init,
+       .dia_update     =       sha1_update,
+       .dia_final      =       sha1_final } }
 };
 
-static int
-init(void)
+static int __init init(void)
 {
-       int ret = -ENOSYS;
+       if (!crypt_s390_func_available(KIMD_SHA_1))
+               return -EOPNOTSUPP;
 
-       if (crypt_s390_func_available(KIMD_SHA_1)){
-               ret = crypto_register_alg(&alg);
-               if (ret == 0){
-                       printk(KERN_INFO "crypt_s390: sha1_s390 loaded.\n");
-               }
-       }
-       return ret;
+       return crypto_register_alg(&alg);
 }
 
-static void __exit
-fini(void)
+static void __exit fini(void)
 {
        crypto_unregister_alg(&alg);
 }
index 8e4e67503fe7f8df35fa8817109d945763001084..78436c696d375c93b2a85f79ae6d2ebb512c3ee2 100644 (file)
@@ -4,7 +4,7 @@
  * s390 implementation of the SHA256 Secure Hash Algorithm.
  *
  * s390 Version:
- *   Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation
+ *   Copyright IBM Corp. 2005,2007
  *   Author(s): Jan Glauber (jang@de.ibm.com)
  *
  * Derived from "crypto/sha256.c"
@@ -143,15 +143,10 @@ static struct crypto_alg alg = {
 
 static int init(void)
 {
-       int ret;
-
        if (!crypt_s390_func_available(KIMD_SHA_256))
-               return -ENOSYS;
+               return -EOPNOTSUPP;
 
-       ret = crypto_register_alg(&alg);
-       if (ret != 0)
-               printk(KERN_INFO "crypt_s390: sha256_s390 couldn't be loaded.");
-       return ret;
+       return crypto_register_alg(&alg);
 }
 
 static void __exit fini(void)
index 5368cf4a350e83471e7a6f332c29f926299631bc..7c621b8ef68370eb7f7dd5f023db1dd0fb87b9e6 100644 (file)
@@ -108,6 +108,8 @@ CONFIG_DEFAULT_MIGRATION_COST=1000000
 CONFIG_COMPAT=y
 CONFIG_SYSVIPC_COMPAT=y
 CONFIG_AUDIT_ARCH=y
+CONFIG_S390_SWITCH_AMODE=y
+CONFIG_S390_EXEC_PROTECT=y
 
 #
 # Code generation options
@@ -431,7 +433,6 @@ CONFIG_TN3270_CONSOLE=y
 CONFIG_TN3215=y
 CONFIG_TN3215_CONSOLE=y
 CONFIG_CCW_CONSOLE=y
-CONFIG_SCLP=y
 CONFIG_SCLP_TTY=y
 CONFIG_SCLP_CONSOLE=y
 CONFIG_SCLP_VT220_TTY=y
@@ -724,9 +725,7 @@ CONFIG_CRYPTO_MANAGER=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_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
@@ -735,12 +734,10 @@ CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=y
 # CONFIG_CRYPTO_LRW is not set
 # CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_DES_S390 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
@@ -755,6 +752,11 @@ CONFIG_CRYPTO_CBC=y
 #
 # Hardware crypto devices
 #
+# CONFIG_CRYPTO_SHA1_S390 is not set
+# CONFIG_CRYPTO_SHA256_S390 is not set
+# CONFIG_CRYPTO_DES_S390 is not set
+# CONFIG_CRYPTO_AES_S390 is not set
+CONFIG_S390_PRNG=m
 
 #
 # Library routines
index f4b00cd81f7c54ef6f284b36a28962556dcb9993..b08d2abf6178fecfc1f89b9dea475e6d906483a5 100644 (file)
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
 
-s390_hypfs-objs := inode.o hypfs_diag.o
+s390_hypfs-objs := inode.o hypfs_diag.o hypfs_vm.o
index f3dbd91965c6ec3729ff161f23475e4cc6d538da..aea572009d60f908a72beb6ec499d7383f001790 100644 (file)
@@ -27,4 +27,13 @@ extern struct dentry *hypfs_create_str(struct super_block *sb,
                                       struct dentry *dir, const char *name,
                                       char *string);
 
+/* LPAR Hypervisor */
+extern int hypfs_diag_init(void);
+extern void hypfs_diag_exit(void);
+extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root);
+
+/* VM Hypervisor */
+extern int hypfs_vm_init(void);
+extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root);
+
 #endif /* _HYPFS_H_ */
diff --git a/arch/s390/hypfs/hypfs_diag.h b/arch/s390/hypfs/hypfs_diag.h
deleted file mode 100644 (file)
index 256b384..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  arch/s390/hypfs_diag.h
- *    Hypervisor filesystem for Linux on s390.
- *
- *    Copyright (C) IBM Corp. 2006
- *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
- */
-
-#ifndef _HYPFS_DIAG_H_
-#define _HYPFS_DIAG_H_
-
-extern int hypfs_diag_init(void);
-extern void hypfs_diag_exit(void);
-extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root);
-
-#endif /* _HYPFS_DIAG_H_ */
diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c
new file mode 100644 (file)
index 0000000..d01fc8f
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ *    Hypervisor filesystem for Linux on s390. z/VM implementation.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <asm/ebcdic.h>
+#include "hypfs.h"
+
+#define NAME_LEN 8
+
+static char local_guest[] = "        ";
+static char all_guests[] = "*       ";
+static char *guest_query;
+
+struct diag2fc_data {
+       __u32 version;
+       __u32 flags;
+       __u64 used_cpu;
+       __u64 el_time;
+       __u64 mem_min_kb;
+       __u64 mem_max_kb;
+       __u64 mem_share_kb;
+       __u64 mem_used_kb;
+       __u32 pcpus;
+       __u32 lcpus;
+       __u32 vcpus;
+       __u32 cpu_min;
+       __u32 cpu_max;
+       __u32 cpu_shares;
+       __u32 cpu_use_samp;
+       __u32 cpu_delay_samp;
+       __u32 page_wait_samp;
+       __u32 idle_samp;
+       __u32 other_samp;
+       __u32 total_samp;
+       char  guest_name[NAME_LEN];
+};
+
+struct diag2fc_parm_list {
+       char userid[NAME_LEN];
+       char aci_grp[NAME_LEN];
+       __u64 addr;
+       __u32 size;
+       __u32 fmt;
+};
+
+static int diag2fc(int size, char* query, void *addr)
+{
+       unsigned long residual_cnt;
+       unsigned long rc;
+       struct diag2fc_parm_list parm_list;
+
+       memcpy(parm_list.userid, query, NAME_LEN);
+       ASCEBC(parm_list.userid, NAME_LEN);
+       parm_list.addr = (unsigned long) addr ;
+       parm_list.size = size;
+       parm_list.fmt = 0x02;
+       memset(parm_list.aci_grp, 0x40, NAME_LEN);
+       rc = -1;
+
+       asm volatile(
+               "       diag    %0,%1,0x2fc\n"
+               "0:\n"
+               EX_TABLE(0b,0b)
+               : "=d" (residual_cnt), "+d" (rc) : "0" (&parm_list) : "memory");
+
+       if ((rc != 0 ) && (rc != -2))
+               return rc;
+       else
+               return -residual_cnt;
+}
+
+static struct diag2fc_data *diag2fc_store(char *query, int *count)
+{
+       int size;
+       struct diag2fc_data *data;
+
+       do {
+               size = diag2fc(0, query, NULL);
+               if (size < 0)
+                       return ERR_PTR(-EACCES);
+               data = vmalloc(size);
+               if (!data)
+                       return ERR_PTR(-ENOMEM);
+               if (diag2fc(size, query, data) == 0)
+                       break;
+               vfree(data);
+       } while (1);
+       *count = (size / sizeof(*data));
+
+       return data;
+}
+
+static void diag2fc_free(void *data)
+{
+       vfree(data);
+}
+
+#define ATTRIBUTE(sb, dir, name, member) \
+do { \
+       void *rc; \
+       rc = hypfs_create_u64(sb, dir, name, member); \
+       if (IS_ERR(rc)) \
+               return PTR_ERR(rc); \
+} while(0)
+
+static int hpyfs_vm_create_guest(struct super_block *sb,
+                                struct dentry *systems_dir,
+                                struct diag2fc_data *data)
+{
+       char guest_name[NAME_LEN + 1] = {};
+       struct dentry *guest_dir, *cpus_dir, *samples_dir, *mem_dir;
+       int dedicated_flag, capped_value;
+
+       capped_value = (data->flags & 0x00000006) >> 1;
+       dedicated_flag = (data->flags & 0x00000008) >> 3;
+
+       /* guest dir */
+       memcpy(guest_name, data->guest_name, NAME_LEN);
+       EBCASC(guest_name, NAME_LEN);
+       strstrip(guest_name);
+       guest_dir = hypfs_mkdir(sb, systems_dir, guest_name);
+       if (IS_ERR(guest_dir))
+               return PTR_ERR(guest_dir);
+       ATTRIBUTE(sb, guest_dir, "onlinetime_us", data->el_time);
+
+       /* logical cpu information */
+       cpus_dir = hypfs_mkdir(sb, guest_dir, "cpus");
+       if (IS_ERR(cpus_dir))
+               return PTR_ERR(cpus_dir);
+       ATTRIBUTE(sb, cpus_dir, "cputime_us", data->used_cpu);
+       ATTRIBUTE(sb, cpus_dir, "capped", capped_value);
+       ATTRIBUTE(sb, cpus_dir, "dedicated", dedicated_flag);
+       ATTRIBUTE(sb, cpus_dir, "count", data->vcpus);
+       ATTRIBUTE(sb, cpus_dir, "weight_min", data->cpu_min);
+       ATTRIBUTE(sb, cpus_dir, "weight_max", data->cpu_max);
+       ATTRIBUTE(sb, cpus_dir, "weight_cur", data->cpu_shares);
+
+       /* memory information */
+       mem_dir = hypfs_mkdir(sb, guest_dir, "mem");
+       if (IS_ERR(mem_dir))
+               return PTR_ERR(mem_dir);
+       ATTRIBUTE(sb, mem_dir, "min_KiB", data->mem_min_kb);
+       ATTRIBUTE(sb, mem_dir, "max_KiB", data->mem_max_kb);
+       ATTRIBUTE(sb, mem_dir, "used_KiB", data->mem_used_kb);
+       ATTRIBUTE(sb, mem_dir, "share_KiB", data->mem_share_kb);
+
+       /* samples */
+       samples_dir = hypfs_mkdir(sb, guest_dir, "samples");
+       if (IS_ERR(samples_dir))
+               return PTR_ERR(samples_dir);
+       ATTRIBUTE(sb, samples_dir, "cpu_using", data->cpu_use_samp);
+       ATTRIBUTE(sb, samples_dir, "cpu_delay", data->cpu_delay_samp);
+       ATTRIBUTE(sb, samples_dir, "mem_delay", data->page_wait_samp);
+       ATTRIBUTE(sb, samples_dir, "idle", data->idle_samp);
+       ATTRIBUTE(sb, samples_dir, "other", data->other_samp);
+       ATTRIBUTE(sb, samples_dir, "total", data->total_samp);
+       return 0;
+}
+
+int hypfs_vm_create_files(struct super_block *sb, struct dentry *root)
+{
+       struct dentry *dir, *file;
+       struct diag2fc_data *data;
+       int rc, i, count = 0;
+
+       data = diag2fc_store(guest_query, &count);
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       /* Hpervisor Info */
+       dir = hypfs_mkdir(sb, root, "hyp");
+       if (IS_ERR(dir)) {
+               rc = PTR_ERR(dir);
+               goto failed;
+       }
+       file = hypfs_create_str(sb, dir, "type", "z/VM Hypervisor");
+       if (IS_ERR(file)) {
+               rc = PTR_ERR(file);
+               goto failed;
+       }
+
+       /* physical cpus */
+       dir = hypfs_mkdir(sb, root, "cpus");
+       if (IS_ERR(dir)) {
+               rc = PTR_ERR(dir);
+               goto failed;
+       }
+       file = hypfs_create_u64(sb, dir, "count", data->lcpus);
+       if (IS_ERR(file)) {
+               rc = PTR_ERR(file);
+               goto failed;
+       }
+
+       /* guests */
+       dir = hypfs_mkdir(sb, root, "systems");
+       if (IS_ERR(dir)) {
+               rc = PTR_ERR(dir);
+               goto failed;
+       }
+
+       for (i = 0; i < count; i++) {
+               rc = hpyfs_vm_create_guest(sb, dir, &(data[i]));
+               if (rc)
+                       goto failed;
+       }
+       diag2fc_free(data);
+       return 0;
+
+failed:
+       diag2fc_free(data);
+       return rc;
+}
+
+int hypfs_vm_init(void)
+{
+       if (diag2fc(0, all_guests, NULL) > 0)
+               guest_query = all_guests;
+       else if (diag2fc(0, local_guest, NULL) > 0)
+               guest_query = local_guest;
+       else
+               return -EACCES;
+
+       return 0;
+}
index b6716c4b993400aa5e0236fa2189980349dc0df0..a4fda7b5364062d7c4aa0fe1dbe1a29afc5e7eb9 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <asm/ebcdic.h>
 #include "hypfs.h"
-#include "hypfs_diag.h"
 
 #define HYPFS_MAGIC 0x687970   /* ASCII 'hyp' */
 #define TMP_SIZE 64            /* size of temporary buffers */
@@ -192,7 +191,10 @@ static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
                goto out;
        }
        hypfs_delete_tree(sb->s_root);
-       rc = hypfs_diag_create_files(sb, sb->s_root);
+       if (MACHINE_IS_VM)
+               rc = hypfs_vm_create_files(sb, sb->s_root);
+       else
+               rc = hypfs_diag_create_files(sb, sb->s_root);
        if (rc) {
                printk(KERN_ERR "hypfs: Update failed\n");
                hypfs_delete_tree(sb->s_root);
@@ -289,7 +291,10 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
                rc = -ENOMEM;
                goto err_alloc;
        }
-       rc = hypfs_diag_create_files(sb, root_dentry);
+       if (MACHINE_IS_VM)
+               rc = hypfs_vm_create_files(sb, root_dentry);
+       else
+               rc = hypfs_diag_create_files(sb, root_dentry);
        if (rc)
                goto err_tree;
        sbi->update_file = hypfs_create_update_file(sb, root_dentry);
@@ -462,11 +467,15 @@ static int __init hypfs_init(void)
 {
        int rc;
 
-       if (MACHINE_IS_VM)
-               return -ENODATA;
-       if (hypfs_diag_init()) {
-               rc = -ENODATA;
-               goto fail_diag;
+       if (MACHINE_IS_VM) {
+               if (hypfs_vm_init())
+                       /* no diag 2fc, just exit */
+                       return -ENODATA;
+       } else {
+               if (hypfs_diag_init()) {
+                       rc = -ENODATA;
+                       goto fail_diag;
+               }
        }
        kset_set_kset_s(&s390_subsys, hypervisor_subsys);
        rc = subsystem_register(&s390_subsys);
@@ -480,7 +489,8 @@ static int __init hypfs_init(void)
 fail_filesystem:
        subsystem_unregister(&s390_subsys);
 fail_sysfs:
-       hypfs_diag_exit();
+       if (!MACHINE_IS_VM)
+               hypfs_diag_exit();
 fail_diag:
        printk(KERN_ERR "hypfs: Initialization failed with rc = %i.\n", rc);
        return rc;
@@ -488,7 +498,8 @@ fail_diag:
 
 static void __exit hypfs_exit(void)
 {
-       hypfs_diag_exit();
+       if (!MACHINE_IS_VM)
+               hypfs_diag_exit();
        unregister_filesystem(&hypfs_type);
        subsystem_unregister(&s390_subsys);
 }
index a81881c9b29760dee818bcff9f3baf348af1b0b7..5492d25d7d69714bc60ffaddb80c3e9d92af6346 100644 (file)
@@ -4,9 +4,9 @@
 
 EXTRA_AFLAGS   := -traditional
 
-obj-y  :=  bitmap.o traps.o time.o process.o reset.o \
+obj-y  :=  bitmap.o traps.o time.o process.o base.o early.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 ipl.o
+           semaphore.o s390_ext.o debug.o irq.o ipl.o
 
 obj-y  += $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y  += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
new file mode 100644 (file)
index 0000000..dc7e525
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ *  arch/s390/kernel/base.S
+ *
+ *    Copyright IBM Corp. 2006,2007
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ *              Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <asm/ptrace.h>
+#include <asm/lowcore.h>
+
+#ifdef CONFIG_64BIT
+
+       .globl  s390_base_mcck_handler
+s390_base_mcck_handler:
+       basr    %r13,0
+0:     lg      %r15,__LC_PANIC_STACK   # load panic stack
+       aghi    %r15,-STACK_FRAME_OVERHEAD
+       larl    %r1,s390_base_mcck_handler_fn
+       lg      %r1,0(%r1)
+       ltgr    %r1,%r1
+       jz      1f
+       basr    %r14,%r1
+1:     la      %r1,4095
+       lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
+       lpswe   __LC_MCK_OLD_PSW
+
+       .section .bss
+       .globl  s390_base_mcck_handler_fn
+s390_base_mcck_handler_fn:
+       .quad   0
+       .previous
+
+       .globl  s390_base_ext_handler
+s390_base_ext_handler:
+       stmg    %r0,%r15,__LC_SAVE_AREA
+       basr    %r13,0
+0:     aghi    %r15,-STACK_FRAME_OVERHEAD
+       larl    %r1,s390_base_ext_handler_fn
+       lg      %r1,0(%r1)
+       ltgr    %r1,%r1
+       jz      1f
+       basr    %r14,%r1
+1:     lmg     %r0,%r15,__LC_SAVE_AREA
+       ni      __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
+       lpswe   __LC_EXT_OLD_PSW
+
+       .section .bss
+       .globl s390_base_ext_handler_fn
+s390_base_ext_handler_fn:
+       .quad   0
+       .previous
+
+       .globl  s390_base_pgm_handler
+s390_base_pgm_handler:
+       stmg    %r0,%r15,__LC_SAVE_AREA
+       basr    %r13,0
+0:     aghi    %r15,-STACK_FRAME_OVERHEAD
+       larl    %r1,s390_base_pgm_handler_fn
+       lg      %r1,0(%r1)
+       ltgr    %r1,%r1
+       jz      1f
+       basr    %r14,%r1
+       lmg     %r0,%r15,__LC_SAVE_AREA
+       lpswe   __LC_PGM_OLD_PSW
+1:     lpswe   disabled_wait_psw-0b(%r13)
+
+       .align  8
+disabled_wait_psw:
+       .quad   0x0002000180000000,0x0000000000000000 + s390_base_pgm_handler
+
+       .section .bss
+       .globl s390_base_pgm_handler_fn
+s390_base_pgm_handler_fn:
+       .quad   0
+       .previous
+
+#else /* CONFIG_64BIT */
+
+       .globl  s390_base_mcck_handler
+s390_base_mcck_handler:
+       basr    %r13,0
+0:     l       %r15,__LC_PANIC_STACK   # load panic stack
+       ahi     %r15,-STACK_FRAME_OVERHEAD
+       l       %r1,2f-0b(%r13)
+       l       %r1,0(%r1)
+       ltr     %r1,%r1
+       jz      1f
+       basr    %r14,%r1
+1:     lm      %r0,%r15,__LC_GPREGS_SAVE_AREA
+       lpsw    __LC_MCK_OLD_PSW
+
+2:     .long   s390_base_mcck_handler_fn
+
+       .section .bss
+       .globl  s390_base_mcck_handler_fn
+s390_base_mcck_handler_fn:
+       .long   0
+       .previous
+
+       .globl  s390_base_ext_handler
+s390_base_ext_handler:
+       stm     %r0,%r15,__LC_SAVE_AREA
+       basr    %r13,0
+0:     ahi     %r15,-STACK_FRAME_OVERHEAD
+       l       %r1,2f-0b(%r13)
+       l       %r1,0(%r1)
+       ltr     %r1,%r1
+       jz      1f
+       basr    %r14,%r1
+1:     lm      %r0,%r15,__LC_SAVE_AREA
+       ni      __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
+       lpsw    __LC_EXT_OLD_PSW
+
+2:     .long   s390_base_ext_handler_fn
+
+       .section .bss
+       .globl  s390_base_ext_handler_fn
+s390_base_ext_handler_fn:
+       .long   0
+       .previous
+
+       .globl  s390_base_pgm_handler
+s390_base_pgm_handler:
+       stm     %r0,%r15,__LC_SAVE_AREA
+       basr    %r13,0
+0:     ahi     %r15,-STACK_FRAME_OVERHEAD
+       l       %r1,2f-0b(%r13)
+       l       %r1,0(%r1)
+       ltr     %r1,%r1
+       jz      1f
+       basr    %r14,%r1
+       lm      %r0,%r15,__LC_SAVE_AREA
+       lpsw    __LC_PGM_OLD_PSW
+
+1:     lpsw    disabled_wait_psw-0b(%r13)
+
+2:     .long   s390_base_pgm_handler_fn
+
+disabled_wait_psw:
+       .align  8
+       .long   0x000a0000,0x00000000 + s390_base_pgm_handler
+
+       .section .bss
+       .globl  s390_base_pgm_handler_fn
+s390_base_pgm_handler_fn:
+       .long   0
+       .previous
+
+#endif /* CONFIG_64BIT */
index 5c46054195cb29e484d9e9bb0c9c072f7fd91222..f1e40ca00d8d97c93ff630010f0a69becd9af815 100644 (file)
@@ -192,7 +192,7 @@ MODULE_AUTHOR("Gerhard Tonn <ton@de.ibm.com>");
 
 #undef cputime_to_timeval
 #define cputime_to_timeval cputime_to_compat_timeval
-static __inline__ void
+static inline void
 cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
 {
        value->tv_usec = cputime % 1000000;
index 71d27c493568babbdfdee79e17a24b481c35cd75..914d49444f92270d6492199bba9ab46d81ccff8d 100644 (file)
 #include <linux/personality.h>
 #include <linux/sched.h>
 
-struct exec_domain s390_exec_domain;
+static struct exec_domain s390_exec_domain;
 
-static int __init
-s390_init (void)
+static int __init s390_init (void)
 {
        s390_exec_domain.name = "Linux/s390";
        s390_exec_domain.handler = NULL;
index 5b33f823863aa5af69c4c99de0d1b2b8afc84b99..666bb6daa148e649d3156aea4b88c65e7c553b3e 100644 (file)
 
 #include "compat_linux.h"
 
+long psw_user32_bits   = (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
+                          PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
+                          PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
+long psw32_user_bits   = (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME |
+                          PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
+                          PSW32_MASK_PSTATE);
  
 /* For this source file, we want overflow handling. */
 
@@ -416,7 +422,7 @@ asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info)
        mm_segment_t old_fs = get_fs ();
        
        set_fs (KERNEL_DS);
-       ret = sys_sysinfo((struct sysinfo __user *) &s);
+       ret = sys_sysinfo((struct sysinfo __force __user *) &s);
        set_fs (old_fs);
        err = put_user (s.uptime, &info->uptime);
        err |= __put_user (s.loads[0], &info->loads[0]);
@@ -445,7 +451,8 @@ asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,
        mm_segment_t old_fs = get_fs ();
        
        set_fs (KERNEL_DS);
-       ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t);
+       ret = sys_sched_rr_get_interval(pid,
+                                       (struct timespec __force __user *) &t);
        set_fs (old_fs);
        if (put_compat_timespec(&t, interval))
                return -EFAULT;
@@ -472,8 +479,8 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
        }
        set_fs (KERNEL_DS);
        ret = sys_rt_sigprocmask(how,
-                                set ? (sigset_t __user *) &s : NULL,
-                                oset ? (sigset_t __user *) &s : NULL,
+                                set ? (sigset_t __force __user *) &s : NULL,
+                                oset ? (sigset_t __force __user *) &s : NULL,
                                 sigsetsize);
        set_fs (old_fs);
        if (ret) return ret;
@@ -499,7 +506,7 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
        mm_segment_t old_fs = get_fs();
                
        set_fs (KERNEL_DS);
-       ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
+       ret = sys_rt_sigpending((sigset_t __force __user *) &s, sigsetsize);
        set_fs (old_fs);
        if (!ret) {
                switch (_NSIG_WORDS) {
@@ -524,7 +531,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
        if (copy_siginfo_from_user32(&info, uinfo))
                return -EFAULT;
        set_fs (KERNEL_DS);
-       ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
+       ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *) &info);
        set_fs (old_fs);
        return ret;
 }
@@ -682,7 +689,7 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offse
                
        set_fs(KERNEL_DS);
        ret = sys_sendfile(out_fd, in_fd,
-                          offset ? (off_t __user *) &of : NULL, count);
+                          offset ? (off_t __force __user *) &of : NULL, count);
        set_fs(old_fs);
        
        if (offset && put_user(of, offset))
@@ -703,7 +710,8 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
                
        set_fs(KERNEL_DS);
        ret = sys_sendfile64(out_fd, in_fd,
-                            offset ? (loff_t __user *) &lof : NULL, count);
+                            offset ? (loff_t __force __user *) &lof : NULL,
+                            count);
        set_fs(old_fs);
        
        if (offset && put_user(lof, offset))
index 1a18e29668ef1758739ae8c799929d8ef8c981d5..e89f8c0c42a058a0ff426dd104a8117222dc13a7 100644 (file)
@@ -115,37 +115,6 @@ typedef struct
         __u32  addr;
 } _psw_t32 __attribute__ ((aligned(8)));
 
-#define PSW32_MASK_PER         0x40000000UL
-#define PSW32_MASK_DAT         0x04000000UL
-#define PSW32_MASK_IO          0x02000000UL
-#define PSW32_MASK_EXT         0x01000000UL
-#define PSW32_MASK_KEY         0x00F00000UL
-#define PSW32_MASK_MCHECK      0x00040000UL
-#define PSW32_MASK_WAIT                0x00020000UL
-#define PSW32_MASK_PSTATE      0x00010000UL
-#define PSW32_MASK_ASC         0x0000C000UL
-#define PSW32_MASK_CC          0x00003000UL
-#define PSW32_MASK_PM          0x00000f00UL
-
-#define PSW32_ADDR_AMODE31     0x80000000UL
-#define PSW32_ADDR_INSN                0x7FFFFFFFUL
-
-#define PSW32_BASE_BITS                0x00080000UL
-
-#define PSW32_ASC_PRIMARY      0x00000000UL
-#define PSW32_ASC_ACCREG       0x00004000UL
-#define PSW32_ASC_SECONDARY    0x00008000UL
-#define PSW32_ASC_HOME         0x0000C000UL
-
-#define PSW32_USER_BITS        (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME | \
-                        PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK | \
-                        PSW32_MASK_PSTATE)
-
-#define PSW32_MASK_MERGE(CURRENT,NEW) \
-        (((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
-         ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))
-
-
 typedef struct
 {
        _psw_t32        psw;
index 861888ab8c13d6cbb18ae89bc716577db5370f1e..887a9881d0d07fa691948aae404806adaad97ddf 100644 (file)
@@ -275,8 +275,8 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
        }
 
        set_fs (KERNEL_DS);
-       ret = do_sigaltstack((stack_t __user *) (uss ? &kss : NULL),
-                            (stack_t __user *) (uoss ? &koss : NULL),
+       ret = do_sigaltstack((stack_t __force __user *) (uss ? &kss : NULL),
+                            (stack_t __force __user *) (uoss ? &koss : NULL),
                             regs->gprs[15]);
        set_fs (old_fs);
 
@@ -298,7 +298,7 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
        _s390_regs_common32 regs32;
        int err, i;
 
-       regs32.psw.mask = PSW32_MASK_MERGE(PSW32_USER_BITS,
+       regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits,
                                           (__u32)(regs->psw.mask >> 32));
        regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
        for (i = 0; i < NUM_GPRS; i++)
@@ -401,7 +401,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
                goto badframe; 
 
        set_fs (KERNEL_DS);
-       do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]);
+       do_sigaltstack((stack_t __force __user *)&st, NULL, regs->gprs[15]);
        set_fs (old_fs);
 
        return regs->gprs[2];
index a5972f1541fea7525afc6c12f868cb7aa5d0efbd..6c89f30c8e31ea39f181fe610dffada543254129 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/ebcdic.h>
 #include <asm/cpcmd.h>
 #include <asm/system.h>
+#include <asm/io.h>
 
 static DEFINE_SPINLOCK(cpcmd_lock);
 static char cpcmd_buf[241];
@@ -88,13 +89,8 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
        int len;
        unsigned long flags;
 
-       if ((rlen == 0) || (response == NULL)
-           || !((unsigned long)response >> 31)) {
-               spin_lock_irqsave(&cpcmd_lock, flags);
-               len = __cpcmd(cmd, response, rlen, response_code);
-               spin_unlock_irqrestore(&cpcmd_lock, flags);
-       }
-       else {
+       if ((virt_to_phys(response) != (unsigned long) response) ||
+                       (((unsigned long)response + rlen) >> 31)) {
                lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
                if (!lowbuf) {
                        printk(KERN_WARNING
@@ -106,6 +102,10 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
                spin_unlock_irqrestore(&cpcmd_lock, flags);
                memcpy(response, lowbuf, rlen);
                kfree(lowbuf);
+       } else {
+               spin_lock_irqsave(&cpcmd_lock, flags);
+               len = __cpcmd(cmd, response, rlen, response_code);
+               spin_unlock_irqrestore(&cpcmd_lock, flags);
        }
        return len;
 }
index 926cceeae0faa27c7d6cb6a44b5141f83aaf46ae..8cc7c9fa64f5fe6e8834e1b7190b831d885cf1ac 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/threads.h>
 #include <linux/kexec.h>
+#include <linux/reboot.h>
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
index bb57bc0e3fc8d760a17a75cd555d29bd6683dcda..f4b62df02aa2721187f514416effebe8af015a60 100644 (file)
@@ -120,7 +120,7 @@ struct debug_view debug_hex_ascii_view = {
        NULL
 };
 
-struct debug_view debug_level_view = {
+static struct debug_view debug_level_view = {
        "level",
        &debug_prolog_level_fn,
        NULL,
@@ -129,7 +129,7 @@ struct debug_view debug_level_view = {
        NULL
 };
 
-struct debug_view debug_pages_view = {
+static struct debug_view debug_pages_view = {
        "pages",
        &debug_prolog_pages_fn,
        NULL,
@@ -138,7 +138,7 @@ struct debug_view debug_pages_view = {
        NULL
 };
 
-struct debug_view debug_flush_view = {
+static struct debug_view debug_flush_view = {
         "flush",
         NULL,
         NULL,
@@ -156,14 +156,14 @@ struct debug_view debug_sprintf_view = {
        NULL
 };
 
-
+/* used by dump analysis tools to determine version of debug feature */
 unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
 
 /* static globals */
 
 static debug_info_t *debug_area_first = NULL;
 static debug_info_t *debug_area_last = NULL;
-DECLARE_MUTEX(debug_lock);
+static DECLARE_MUTEX(debug_lock);
 
 static int initialized;
 
@@ -905,7 +905,7 @@ static struct ctl_table s390dbf_dir_table[] = {
        { .ctl_name = 0 }
 };
 
-struct ctl_table_header *s390dbf_sysctl_header;
+static struct ctl_table_header *s390dbf_sysctl_header;
 
 void
 debug_stop_all(void)
@@ -1300,8 +1300,7 @@ out:
  * flushes debug areas
  */
  
-void
-debug_flush(debug_info_t* id, int area)
+static void debug_flush(debug_info_t* id, int area)
 {
         unsigned long flags;
         int i,j;
@@ -1511,8 +1510,7 @@ out:
 /*
  * clean up module
  */
-void
-__exit debug_exit(void)
+static void __exit debug_exit(void)
 {
        debugfs_remove(debug_debugfs_root_entry);
        unregister_sysctl_table(s390dbf_sysctl_header);
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
new file mode 100644 (file)
index 0000000..e518dd5
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ *  arch/s390/kernel/early.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Hongjie Yang <hongjie@us.ibm.com>,
+ *              Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/lockdep.h>
+#include <linux/module.h>
+#include <linux/pfn.h>
+#include <linux/uaccess.h>
+#include <asm/lowcore.h>
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/cpcmd.h>
+#include <asm/sclp.h>
+
+/*
+ * Create a Kernel NSS if the SAVESYS= parameter is defined
+ */
+#define DEFSYS_CMD_SIZE                96
+#define SAVESYS_CMD_SIZE       32
+
+char kernel_nss_name[NSS_NAME_SIZE + 1];
+
+#ifdef CONFIG_SHARED_KERNEL
+static noinline __init void create_kernel_nss(void)
+{
+       unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
+#ifdef CONFIG_BLK_DEV_INITRD
+       unsigned int sinitrd_pfn, einitrd_pfn;
+#endif
+       int response;
+       char *savesys_ptr;
+       char upper_command_line[COMMAND_LINE_SIZE];
+       char defsys_cmd[DEFSYS_CMD_SIZE];
+       char savesys_cmd[SAVESYS_CMD_SIZE];
+
+       /* Do nothing if we are not running under VM */
+       if (!MACHINE_IS_VM)
+               return;
+
+       /* Convert COMMAND_LINE to upper case */
+       for (i = 0; i < strlen(COMMAND_LINE); i++)
+               upper_command_line[i] = toupper(COMMAND_LINE[i]);
+
+       savesys_ptr = strstr(upper_command_line, "SAVESYS=");
+
+       if (!savesys_ptr)
+               return;
+
+       savesys_ptr += 8;    /* Point to the beginning of the NSS name */
+       for (i = 0; i < NSS_NAME_SIZE; i++) {
+               if (savesys_ptr[i] == ' ' || savesys_ptr[i] == '\0')
+                       break;
+               kernel_nss_name[i] = savesys_ptr[i];
+       }
+
+       stext_pfn = PFN_DOWN(__pa(&_stext));
+       eshared_pfn = PFN_DOWN(__pa(&_eshared));
+       end_pfn = PFN_UP(__pa(&_end));
+       min_size = end_pfn << 2;
+
+       sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X",
+               kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1,
+               eshared_pfn, end_pfn);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (INITRD_START && INITRD_SIZE) {
+               sinitrd_pfn = PFN_DOWN(__pa(INITRD_START));
+               einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE));
+               min_size = einitrd_pfn << 2;
+               sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd,
+               sinitrd_pfn, einitrd_pfn);
+       }
+#endif
+
+       sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size);
+       sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
+               kernel_nss_name, kernel_nss_name);
+
+       __cpcmd(defsys_cmd, NULL, 0, &response);
+
+       if (response != 0)
+               return;
+
+       __cpcmd(savesys_cmd, NULL, 0, &response);
+
+       if (response != strlen(savesys_cmd))
+               return;
+
+       ipl_flags = IPL_NSS_VALID;
+}
+
+#else /* CONFIG_SHARED_KERNEL */
+
+static inline void create_kernel_nss(void) { }
+
+#endif /* CONFIG_SHARED_KERNEL */
+
+/*
+ * Clear bss memory
+ */
+static noinline __init void clear_bss_section(void)
+{
+       memset(__bss_start, 0, _end - __bss_start);
+}
+
+/*
+ * Initialize storage key for kernel pages
+ */
+static noinline __init void init_kernel_storage_key(void)
+{
+       unsigned long end_pfn, init_pfn;
+
+       end_pfn = PFN_UP(__pa(&_end));
+
+       for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++)
+               page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
+}
+
+static noinline __init void detect_machine_type(void)
+{
+       struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
+
+       asm volatile("stidp %0" : "=m" (S390_lowcore.cpu_data.cpu_id));
+
+       /* Running under z/VM ? */
+       if (cpuinfo->cpu_id.version == 0xff)
+               machine_flags |= 1;
+
+       /* Running on a P/390 ? */
+       if (cpuinfo->cpu_id.machine == 0x7490)
+               machine_flags |= 4;
+}
+
+static noinline __init int memory_fast_detect(void)
+{
+
+       unsigned long val0 = 0;
+       unsigned long val1 = 0xc;
+       int ret = -ENOSYS;
+
+       if (ipl_flags & IPL_NSS_VALID)
+               return -ENOSYS;
+
+       asm volatile(
+               "       diag    %1,%2,0x260\n"
+               "0:     lhi     %0,0\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (ret), "+d" (val0), "+d" (val1) : : "cc");
+
+       if (ret || val0 != val1)
+               return -ENOSYS;
+
+       memory_chunk[0].size = val0;
+       return 0;
+}
+
+#define ADDR2G (1UL << 31)
+
+static noinline __init unsigned long sclp_memory_detect(void)
+{
+       struct sclp_readinfo_sccb *sccb;
+       unsigned long long memsize;
+
+       sccb = &s390_readinfo_sccb;
+
+       if (sccb->header.response_code != 0x10)
+               return 0;
+
+       if (sccb->rnsize)
+               memsize = sccb->rnsize << 20;
+       else
+               memsize = sccb->rnsize2 << 20;
+       if (sccb->rnmax)
+               memsize *= sccb->rnmax;
+       else
+               memsize *= sccb->rnmax2;
+#ifndef CONFIG_64BIT
+       /*
+        * Can't deal with more than 2G in 31 bit addressing mode, so
+        * limit the value in order to avoid strange side effects.
+        */
+       if (memsize > ADDR2G)
+               memsize = ADDR2G;
+#endif
+       return (unsigned long) memsize;
+}
+
+static inline __init unsigned long __tprot(unsigned long addr)
+{
+       int cc = -1;
+
+       asm volatile(
+               "       tprot   0(%1),0\n"
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (cc) : "a" (addr) : "cc");
+       return (unsigned long)cc;
+}
+
+/* Checking memory in 128KB increments. */
+#define CHUNK_INCR     (1UL << 17)
+
+static noinline __init void find_memory_chunks(unsigned long memsize)
+{
+       unsigned long addr = 0, old_addr = 0;
+       unsigned long old_cc = CHUNK_READ_WRITE;
+       unsigned long cc;
+       int chunk = 0;
+
+       while (chunk < MEMORY_CHUNKS) {
+               cc = __tprot(addr);
+               while (cc == old_cc) {
+                       addr += CHUNK_INCR;
+                       cc = __tprot(addr);
+#ifndef CONFIG_64BIT
+                       if (addr == ADDR2G)
+                               break;
+#endif
+               }
+
+               if (old_addr != addr &&
+                   (old_cc == CHUNK_READ_WRITE || old_cc == CHUNK_READ_ONLY)) {
+                       memory_chunk[chunk].addr = old_addr;
+                       memory_chunk[chunk].size = addr - old_addr;
+                       memory_chunk[chunk].type = old_cc;
+                       chunk++;
+               }
+
+               old_addr = addr;
+               old_cc = cc;
+
+#ifndef CONFIG_64BIT
+               if (addr == ADDR2G)
+                       break;
+#endif
+               /*
+                * Finish memory detection at the first hole, unless
+                * - we reached the hsa -> skip it.
+                * - we know there must be more.
+                */
+               if (cc == -1UL && !memsize && old_addr != ADDR2G)
+                       break;
+               if (memsize && addr >= memsize)
+                       break;
+       }
+}
+
+static __init void early_pgm_check_handler(void)
+{
+       unsigned long addr;
+       const struct exception_table_entry *fixup;
+
+       addr = S390_lowcore.program_old_psw.addr;
+       fixup = search_exception_tables(addr & PSW_ADDR_INSN);
+       if (!fixup)
+               disabled_wait(0);
+       S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE;
+}
+
+static noinline __init void setup_lowcore_early(void)
+{
+       psw_t psw;
+
+       psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
+       psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler;
+       S390_lowcore.external_new_psw = psw;
+       psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
+       S390_lowcore.program_new_psw = psw;
+       s390_base_pgm_handler_fn = early_pgm_check_handler;
+}
+
+/*
+ * Save ipl parameters, clear bss memory, initialize storage keys
+ * and create a kernel NSS at startup if the SAVESYS= parm is defined
+ */
+void __init startup_init(void)
+{
+       unsigned long memsize;
+
+       ipl_save_parameters();
+       clear_bss_section();
+       init_kernel_storage_key();
+       lockdep_init();
+       lockdep_off();
+       detect_machine_type();
+       create_kernel_nss();
+       sort_main_extable();
+       setup_lowcore_early();
+       sclp_readinfo_early();
+       memsize = sclp_memory_detect();
+       if (memory_fast_detect() < 0)
+               find_memory_chunks(memsize);
+       lockdep_on();
+}
index bb0f973137f0d4953ac4a016ab9ee1b9281e7c4b..cc0dc609d738c7e148acfd3855da42f8e303b784 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/module.h>
 #include <asm/types.h>
+#include <asm/ebcdic.h>
 
 /*
  * ASCII (IBM PC 437)  -> EBCDIC 037
index eca507050e47db9e575df233afbda59b0ed45cc7..453fd3b4edea6e59d8a2600f43d72af32c43b43f 100644 (file)
@@ -51,175 +51,14 @@ startup_continue:
        st      %r15,__LC_KERNEL_STACK  # set end of kernel stack
        ahi     %r15,-96
        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
-
-       l       %r14,.Lipl_save_parameters-.LPG1(%r13)
-       basr    %r14,%r14
 #
-# clear bss memory
+# Save ipl parameters, clear bss memory, initialize storage key for kernel pages,
+# and create a kernel NSS if the SAVESYS= parm is defined
 #
-       l       %r2,.Lbss_bgn-.LPG1(%r13) # start of bss
-       l       %r3,.Lbss_end-.LPG1(%r13) # end of bss
-       sr      %r3,%r2                 # length of bss
-       sr      %r4,%r4
-       sr      %r5,%r5                 # set src,length and pad to zero
-       sr      %r0,%r0
-       mvcle   %r2,%r4,0               # clear mem
-       jo      .-4                     # branch back, if not finish
-
-       l       %r2,.Lrcp-.LPG1(%r13)   # Read SCP forced command word
-.Lservicecall:
-       stosm   .Lpmask-.LPG1(%r13),0x01        # authorize ext interrupts
-
-       stctl   %r0, %r0,.Lcr-.LPG1(%r13)       # get cr0
-       la      %r1,0x200               # set bit 22
-       o       %r1,.Lcr-.LPG1(%r13)    # or old cr0 with r1
-       st      %r1,.Lcr-.LPG1(%r13)
-       lctl    %r0, %r0,.Lcr-.LPG1(%r13)       # load modified cr0
-
-       mvc     __LC_EXT_NEW_PSW(8),.Lpcext-.LPG1(%r13) # set postcall psw
-       la      %r1, .Lsclph-.LPG1(%r13)
-       a       %r1,__LC_EXT_NEW_PSW+4  # set handler
-       st      %r1,__LC_EXT_NEW_PSW+4
-
-       l       %r4,.Lsccbaddr-.LPG1(%r13) # %r4 is our index for sccb stuff
-       lr      %r1,%r4                 # our sccb
-       .insn   rre,0xb2200000,%r2,%r1  # service call
-       ipm     %r1
-       srl     %r1,28                  # get cc code
-       xr      %r3, %r3
-       chi     %r1,3
-       be      .Lfchunk-.LPG1(%r13)    # leave
-       chi     %r1,2
-       be      .Lservicecall-.LPG1(%r13)
-       lpsw    .Lwaitsclp-.LPG1(%r13)
-.Lsclph:
-       lh      %r1,.Lsccbr-.Lsccb(%r4)
-       chi     %r1,0x10                # 0x0010 is the sucess code
-       je      .Lprocsccb              # let's process the sccb
-       chi     %r1,0x1f0
-       bne     .Lfchunk-.LPG1(%r13)    # unhandled error code
-       c       %r2, .Lrcp-.LPG1(%r13)  # Did we try Read SCP forced
-       bne     .Lfchunk-.LPG1(%r13)    # if no, give up
-       l       %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP
-       b       .Lservicecall-.LPG1(%r13)
-.Lprocsccb:
-       lhi     %r1,0
-       icm     %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0
-       jnz     .Lscnd
-       lhi     %r1,0x800               # otherwise report 2GB
-.Lscnd:
-       lhi     %r3,0x800               # limit reported memory size to 2GB
-       cr      %r1,%r3
-       jl      .Lno2gb
-       lr      %r1,%r3
-.Lno2gb:
-       xr      %r3,%r3                 # same logic
-       ic      %r3,.Lscpa1-.Lsccb(%r4)
-       chi     %r3,0x00
-       jne     .Lcompmem
-       l       %r3,.Lscpa2-.Lsccb(%r4)
-.Lcompmem:
-       mr      %r2,%r1                 # mem in MB on 128-bit
-       l       %r1,.Lonemb-.LPG1(%r13)
-       mr      %r2,%r1                 # mem size in bytes in %r3
-       b       .Lfchunk-.LPG1(%r13)
-
-       .align 4
-.Lipl_save_parameters:
-       .long   ipl_save_parameters
-.Linittu:
-       .long   init_thread_union
-.Lpmask:
-       .byte   0
-       .align  8
-.Lpcext:.long  0x00080000,0x80000000
-.Lcr:
-       .long   0x00                    # place holder for cr0
-       .align  8
-.Lwaitsclp:
-       .long 0x010a0000,0x80000000 + .Lsclph
-.Lrcp:
-       .int    0x00120001              # Read SCP forced code
-.Lrcp2:
-       .int    0x00020001              # Read SCP code
-.Lonemb:
-       .int    0x100000
-.Lfchunk:
+       l       %r14,.Lstartup_init-.LPG1(%r13)
+       basr    %r14,%r14
 
-#
-# find memory chunks.
-#
-       lr      %r9,%r3                 # end of mem
-       mvc     __LC_PGM_NEW_PSW(8),.Lpcmem-.LPG1(%r13)
-       la      %r1,1                   # test in increments of 128KB
-       sll     %r1,17
-       l       %r3,.Lmchunk-.LPG1(%r13) # get pointer to memory_chunk array
-       slr     %r4,%r4                 # set start of chunk to zero
-       slr     %r5,%r5                 # set end of chunk to zero
-       slr     %r6,%r6                 # set access code to zero
-       la      %r10,MEMORY_CHUNKS      # number of chunks
-.Lloop:
-       tprot   0(%r5),0                # test protection of first byte
-       ipm     %r7
-       srl     %r7,28
-       clr     %r6,%r7                 # compare cc with last access code
-       be      .Lsame-.LPG1(%r13)
-       lhi     %r8,0                   # no program checks
-       b       .Lsavchk-.LPG1(%r13)
-.Lsame:
-       ar      %r5,%r1                 # add 128KB to end of chunk
-       bno     .Lloop-.LPG1(%r13)      # r1 < 0x80000000 -> loop
-.Lchkmem:                              # > 2GB or tprot got a program check
-       lhi     %r8,1                   # set program check flag
-.Lsavchk:
-       clr     %r4,%r5                 # chunk size > 0?
-       be      .Lchkloop-.LPG1(%r13)
-       st      %r4,0(%r3)              # store start address of chunk
-       lr      %r0,%r5
-       slr     %r0,%r4
-       st      %r0,4(%r3)              # store size of chunk
-       st      %r6,8(%r3)              # store type of chunk
-       la      %r3,12(%r3)
-       ahi     %r10,-1                 # update chunk number
-.Lchkloop:
-       lr      %r6,%r7                 # set access code to last cc
-       # we got an exception or we're starting a new
-       # chunk , we must check if we should
-       # still try to find valid memory (if we detected
-       # the amount of available storage), and if we
-       # have chunks left
-       xr      %r0,%r0
-       clr     %r0,%r9                 # did we detect memory?
-       je      .Ldonemem               # if not, leave
-       chi     %r10,0                  # do we have chunks left?
-       je      .Ldonemem
-       chi     %r8,1                   # program check ?
-       je      .Lpgmchk
-       lr      %r4,%r5                 # potential new chunk
-       alr     %r5,%r1                 # add 128KB to end of chunk
-       j       .Llpcnt
-.Lpgmchk:
-       alr     %r5,%r1                 # add 128KB to end of chunk
-       lr      %r4,%r5                 # potential new chunk
-.Llpcnt:
-       clr     %r5,%r9                 # should we go on?
-       jl      .Lloop
-.Ldonemem:
        l       %r12,.Lmflags-.LPG1(%r13) # get address of machine_flags
-#
-# find out if we are running under VM
-#
-       stidp   __LC_CPUID              # store cpuid
-       tm      __LC_CPUID,0xff         # running under VM ?
-       bno     .Lnovm-.LPG1(%r13)
-       oi      3(%r12),1               # set VM flag
-.Lnovm:
-       lh      %r0,__LC_CPUID+4        # get cpu version
-       chi     %r0,0x7490              # running on a P/390 ?
-       bne     .Lnop390-.LPG1(%r13)
-       oi      3(%r12),4               # set P/390 flag
-.Lnop390:
-
 #
 # find out if we have an IEEE fpu
 #
@@ -295,7 +134,6 @@ startup_continue:
        .long   0                       # cr15: linkage stack operations
 .Lduct:        .long   0,0,0,0,0,0,0,0
        .long   0,0,0,0,0,0,0,0
-.Lpcmem:.long  0x00080000,0x80000000 + .Lchkmem
 .Lpcfpu:.long  0x00080000,0x80000000 + .Lchkfpu
 .Lpccsp:.long  0x00080000,0x80000000 + .Lchkcsp
 .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg
@@ -306,7 +144,9 @@ startup_continue:
 .Lbss_bgn:  .long __bss_start
 .Lbss_end:  .long _end
 .Lparmaddr: .long PARMAREA
-.Lsccbaddr: .long .Lsccb
+.Linittu:   .long init_thread_union
+.Lstartup_init:
+           .long startup_init
 
        .globl ipl_schib
 ipl_schib:
@@ -322,26 +162,6 @@ ipl_devno:
        .word 0
 
        .org    0x12000
-.globl s390_readinfo_sccb
-s390_readinfo_sccb:
-.Lsccb:
-       .hword  0x1000                  # length, one page
-       .byte   0x00,0x00,0x00
-       .byte   0x80                    # variable response bit set
-.Lsccbr:
-       .hword  0x00                    # response code
-.Lscpincr1:
-       .hword  0x00
-.Lscpa1:
-       .byte   0x00
-       .fill   89,1,0
-.Lscpa2:
-       .int    0x00
-.Lscpincr2:
-       .quad   0x00
-       .fill   3984,1,0
-       .org    0x13000
-
 #ifdef CONFIG_SHARED_KERNEL
        .org    0x100000
 #endif
index 6ba3f4512dd1a1ad26a4d4e0993c9b6feaaf6bc6..b8fec4e5c5d4ac3bd5e8da5b527901445ee78542 100644 (file)
@@ -58,182 +58,14 @@ startup_continue:
        stg     %r15,__LC_KERNEL_STACK  # set end of kernel stack
        aghi    %r15,-160
        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain
-
-       brasl   %r14,ipl_save_parameters
 #
-# clear bss memory
+# Save ipl parameters, clear bss memory, initialize storage key for kernel pages,
+# and create a kernel NSS if the SAVESYS= parm is defined
 #
-       larl    %r2,__bss_start         # start of bss segment
-       larl    %r3,_end                # end of bss segment
-       sgr     %r3,%r2                 # length of bss
-       sgr     %r4,%r4                 #
-       sgr     %r5,%r5                 # set src,length and pad to zero
-       mvcle   %r2,%r4,0               # clear mem
-       jo      .-4                     # branch back, if not finish
+       brasl   %r14,startup_init
                                        # set program check new psw mask
        mvc     __LC_PGM_NEW_PSW(8),.Lpcmsk-.LPG1(%r13)
-       larl    %r1,.Lslowmemdetect     # set program check address
-       stg     %r1,__LC_PGM_NEW_PSW+8
-       lghi    %r1,0xc
-       diag    %r0,%r1,0x260           # get memory size of virtual machine
-       cgr     %r0,%r1                 # different? -> old detection routine
-       jne     .Lslowmemdetect
-       aghi    %r1,1                   # size is one more than end
-       larl    %r2,memory_chunk
-       stg     %r1,8(%r2)              # store size of chunk
-       j       .Ldonemem
-
-.Lslowmemdetect:
-       l       %r2,.Lrcp-.LPG1(%r13)   # Read SCP forced command word
-.Lservicecall:
-       stosm   .Lpmask-.LPG1(%r13),0x01        # authorize ext interrupts
-
-       stctg   %r0,%r0,.Lcr-.LPG1(%r13)        # get cr0
-       la      %r1,0x200               # set bit 22
-       og      %r1,.Lcr-.LPG1(%r13)    # or old cr0 with r1
-       stg     %r1,.Lcr-.LPG1(%r13)
-       lctlg   %r0,%r0,.Lcr-.LPG1(%r13)        # load modified cr0
-
-       mvc     __LC_EXT_NEW_PSW(8),.Lpcmsk-.LPG1(%r13) # set postcall psw
-       larl    %r1,.Lsclph
-       stg     %r1,__LC_EXT_NEW_PSW+8  # set handler
-
-       larl    %r4,.Lsccb              # %r4 is our index for sccb stuff
-       lgr     %r1,%r4                 # our sccb
-       .insn   rre,0xb2200000,%r2,%r1  # service call
-       ipm     %r1
-       srl     %r1,28                  # get cc code
-       xr      %r3,%r3
-       chi     %r1,3
-       be      .Lfchunk-.LPG1(%r13)    # leave
-       chi     %r1,2
-       be      .Lservicecall-.LPG1(%r13)
-       lpswe   .Lwaitsclp-.LPG1(%r13)
-.Lsclph:
-       lh      %r1,.Lsccbr-.Lsccb(%r4)
-       chi     %r1,0x10                # 0x0010 is the sucess code
-       je      .Lprocsccb              # let's process the sccb
-       chi     %r1,0x1f0
-       bne     .Lfchunk-.LPG1(%r13)    # unhandled error code
-       c       %r2,.Lrcp-.LPG1(%r13)   # Did we try Read SCP forced
-       bne     .Lfchunk-.LPG1(%r13)    # if no, give up
-       l       %r2,.Lrcp2-.LPG1(%r13)  # try with Read SCP
-       b       .Lservicecall-.LPG1(%r13)
-.Lprocsccb:
-       lghi    %r1,0
-       icm     %r1,3,.Lscpincr1-.Lsccb(%r4)    # use this one if != 0
-       jnz     .Lscnd
-       lg      %r1,.Lscpincr2-.Lsccb(%r4)      # otherwise use this one
-.Lscnd:
-       xr      %r3,%r3                 # same logic
-       ic      %r3,.Lscpa1-.Lsccb(%r4)
-       chi     %r3,0x00
-       jne     .Lcompmem
-       l       %r3,.Lscpa2-.Lsccb(%r4)
-.Lcompmem:
-       mlgr    %r2,%r1                 # mem in MB on 128-bit
-       l       %r1,.Lonemb-.LPG1(%r13)
-       mlgr    %r2,%r1                 # mem size in bytes in %r3
-       b       .Lfchunk-.LPG1(%r13)
-
-       .align  4
-.Lpmask:
-       .byte   0
-       .align  8
-.Lcr:
-       .quad   0x00  # place holder for cr0
-.Lwaitsclp:
-       .quad   0x0102000180000000,.Lsclph
-.Lrcp:
-       .int    0x00120001 # Read SCP forced code
-.Lrcp2:
-       .int    0x00020001 # Read SCP code
-.Lonemb:
-       .int    0x100000
-
-.Lfchunk:
-
-#
-# find memory chunks.
-#
-       lgr     %r9,%r3                 # end of mem
-       larl    %r1,.Lchkmem            # set program check address
-       stg     %r1,__LC_PGM_NEW_PSW+8
-       la      %r1,1                   # test in increments of 128KB
-       sllg    %r1,%r1,17
-       larl    %r3,memory_chunk
-       slgr    %r4,%r4                 # set start of chunk to zero
-       slgr    %r5,%r5                 # set end of chunk to zero
-       slr     %r6,%r6                 # set access code to zero
-       la      %r10,MEMORY_CHUNKS      # number of chunks
-.Lloop:
-       tprot   0(%r5),0                # test protection of first byte
-       ipm     %r7
-       srl     %r7,28
-       clr     %r6,%r7                 # compare cc with last access code
-       je      .Lsame
-       lghi    %r8,0                   # no program checks
-       j       .Lsavchk
-.Lsame:
-       algr    %r5,%r1                 # add 128KB to end of chunk
-                                       # no need to check here,
-       brc     12,.Lloop               # this is the same chunk
-.Lchkmem:                              # > 16EB or tprot got a program check
-       lghi    %r8,1                   # set program check flag
-.Lsavchk:
-       clgr    %r4,%r5                 # chunk size > 0?
-       je      .Lchkloop
-       stg     %r4,0(%r3)              # store start address of chunk
-       lgr     %r0,%r5
-       slgr    %r0,%r4
-       stg     %r0,8(%r3)              # store size of chunk
-       st      %r6,20(%r3)             # store type of chunk
-       la      %r3,24(%r3)
-       ahi     %r10,-1                 # update chunk number
-.Lchkloop:
-       lr      %r6,%r7                 # set access code to last cc
-       # we got an exception or we're starting a new
-       # chunk , we must check if we should
-       # still try to find valid memory (if we detected
-       # the amount of available storage), and if we
-       # have chunks left
-       lghi    %r4,1
-       sllg    %r4,%r4,31
-       clgr    %r5,%r4
-       je      .Lhsaskip
-       xr      %r0, %r0
-       clgr    %r0, %r9                # did we detect memory?
-       je      .Ldonemem               # if not, leave
-       chi     %r10, 0                 # do we have chunks left?
-       je      .Ldonemem
-.Lhsaskip:
-       chi     %r8,1                   # program check ?
-       je      .Lpgmchk
-       lgr     %r4,%r5                 # potential new chunk
-       algr    %r5,%r1                 # add 128KB to end of chunk
-       j       .Llpcnt
-.Lpgmchk:
-       algr    %r5,%r1                 # add 128KB to end of chunk
-       lgr     %r4,%r5                 # potential new chunk
-.Llpcnt:
-       clgr    %r5,%r9                 # should we go on?
-       jl      .Lloop
-.Ldonemem:
-
        larl    %r12,machine_flags
-#
-# find out if we are running under VM
-#
-       stidp   __LC_CPUID              # store cpuid
-       tm      __LC_CPUID,0xff         # running under VM ?
-       bno     0f-.LPG1(%r13)
-       oi      7(%r12),1               # set VM flag
-0:     lh      %r0,__LC_CPUID+4        # get cpu version
-       chi     %r0,0x7490              # running on a P/390 ?
-       bne     1f-.LPG1(%r13)
-       oi      7(%r12),4               # set P/390 flag
-1:
-
 #
 # find out if we have the MVPG instruction
 #
@@ -336,25 +168,6 @@ ipl_devno:
        .word 0
 
        .org    0x12000
-.globl s390_readinfo_sccb
-s390_readinfo_sccb:
-.Lsccb:
-       .hword  0x1000                  # length, one page
-       .byte   0x00,0x00,0x00
-       .byte   0x80                    # variable response bit set
-.Lsccbr:
-       .hword  0x00                    # response code
-.Lscpincr1:
-       .hword  0x00
-.Lscpa1:
-       .byte   0x00
-       .fill   89,1,0
-.Lscpa2:
-       .int    0x00
-.Lscpincr2:
-       .quad   0x00
-       .fill   3984,1,0
-       .org    0x13000
 
 #ifdef CONFIG_SHARED_KERNEL
        .org    0x100000
index 9e9972e8a52b64363241bfc11dc3061ad3cff1e4..052259530651cddcd12eba6f415b4349947962f6 100644 (file)
 #include <asm/cio.h>
 #include <asm/ebcdic.h>
 #include <asm/reset.h>
+#include <asm/sclp.h>
 
 #define IPL_PARM_BLOCK_VERSION 0
-#define LOADPARM_LEN 8
 
-extern char s390_readinfo_sccb[];
-#define SCCB_VALID (*((__u16*)&s390_readinfo_sccb[6]) == 0x0010)
-#define SCCB_LOADPARM (&s390_readinfo_sccb[24])
-#define SCCB_FLAG (s390_readinfo_sccb[91])
+#define SCCB_VALID (s390_readinfo_sccb.header.response_code == 0x10)
+#define SCCB_LOADPARM (&s390_readinfo_sccb.loadparm)
+#define SCCB_FLAG (s390_readinfo_sccb.flags)
 
 enum ipl_type {
        IPL_TYPE_NONE    = 1,
        IPL_TYPE_UNKNOWN = 2,
        IPL_TYPE_CCW     = 4,
        IPL_TYPE_FCP     = 8,
+       IPL_TYPE_NSS     = 16,
 };
 
 #define IPL_NONE_STR    "none"
 #define IPL_UNKNOWN_STR  "unknown"
 #define IPL_CCW_STR     "ccw"
 #define IPL_FCP_STR     "fcp"
+#define IPL_NSS_STR     "nss"
 
 static char *ipl_type_str(enum ipl_type type)
 {
@@ -50,6 +51,8 @@ static char *ipl_type_str(enum ipl_type type)
                return IPL_CCW_STR;
        case IPL_TYPE_FCP:
                return IPL_FCP_STR;
+       case IPL_TYPE_NSS:
+               return IPL_NSS_STR;
        case IPL_TYPE_UNKNOWN:
        default:
                return IPL_UNKNOWN_STR;
@@ -64,6 +67,7 @@ enum ipl_method {
        IPL_METHOD_FCP_RO_DIAG,
        IPL_METHOD_FCP_RW_DIAG,
        IPL_METHOD_FCP_RO_VM,
+       IPL_METHOD_NSS,
 };
 
 enum shutdown_action {
@@ -114,11 +118,14 @@ enum diag308_rc {
 static int diag308_set_works = 0;
 
 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
+
 static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
 static enum ipl_method reipl_method = IPL_METHOD_NONE;
 static struct ipl_parameter_block *reipl_block_fcp;
 static struct ipl_parameter_block *reipl_block_ccw;
 
+static char reipl_nss_name[NSS_NAME_SIZE + 1];
+
 static int dump_capabilities = IPL_TYPE_NONE;
 static enum ipl_type dump_type = IPL_TYPE_NONE;
 static enum ipl_method dump_method = IPL_METHOD_NONE;
@@ -173,6 +180,24 @@ static struct subsys_attribute sys_##_prefix##_##_name##_attr =            \
                        sys_##_prefix##_##_name##_show,                 \
                        sys_##_prefix##_##_name##_store);
 
+#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
+static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys,        \
+               char *page)                                             \
+{                                                                      \
+       return sprintf(page, _fmt_out, _value);                         \
+}                                                                      \
+static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
+               const char *buf, size_t len)                            \
+{                                                                      \
+       if (sscanf(buf, _fmt_in, _value) != 1)                          \
+               return -EINVAL;                                         \
+       return len;                                                     \
+}                                                                      \
+static struct subsys_attribute sys_##_prefix##_##_name##_attr =                \
+       __ATTR(_name,(S_IRUGO | S_IWUSR),                               \
+                       sys_##_prefix##_##_name##_show,                 \
+                       sys_##_prefix##_##_name##_store);
+
 static void make_attrs_ro(struct attribute **attrs)
 {
        while (*attrs) {
@@ -189,6 +214,8 @@ static enum ipl_type ipl_get_type(void)
 {
        struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
 
+       if (ipl_flags & IPL_NSS_VALID)
+               return IPL_TYPE_NSS;
        if (!(ipl_flags & IPL_DEVNO_VALID))
                return IPL_TYPE_UNKNOWN;
        if (!(ipl_flags & IPL_PARMBLOCK_VALID))
@@ -324,6 +351,20 @@ static struct attribute_group ipl_ccw_attr_group = {
        .attrs = ipl_ccw_attrs,
 };
 
+/* NSS ipl device attributes */
+
+DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name);
+
+static struct attribute *ipl_nss_attrs[] = {
+       &sys_ipl_type_attr.attr,
+       &sys_ipl_nss_name_attr.attr,
+       NULL,
+};
+
+static struct attribute_group ipl_nss_attr_group = {
+       .attrs = ipl_nss_attrs,
+};
+
 /* UNKNOWN ipl device attributes */
 
 static struct attribute *ipl_unknown_attrs[] = {
@@ -432,6 +473,21 @@ static struct attribute_group reipl_ccw_attr_group = {
        .attrs = reipl_ccw_attrs,
 };
 
+
+/* NSS reipl device attributes */
+
+DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name);
+
+static struct attribute *reipl_nss_attrs[] = {
+       &sys_reipl_nss_name_attr.attr,
+       NULL,
+};
+
+static struct attribute_group reipl_nss_attr_group = {
+       .name  = IPL_NSS_STR,
+       .attrs = reipl_nss_attrs,
+};
+
 /* reipl type */
 
 static int reipl_set_type(enum ipl_type type)
@@ -454,6 +510,9 @@ static int reipl_set_type(enum ipl_type type)
                else
                        reipl_method = IPL_METHOD_FCP_RO_DIAG;
                break;
+       case IPL_TYPE_NSS:
+               reipl_method = IPL_METHOD_NSS;
+               break;
        default:
                reipl_method = IPL_METHOD_NONE;
        }
@@ -475,6 +534,8 @@ static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf,
                rc = reipl_set_type(IPL_TYPE_CCW);
        else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
                rc = reipl_set_type(IPL_TYPE_FCP);
+       else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
+               rc = reipl_set_type(IPL_TYPE_NSS);
        return (rc != 0) ? rc : len;
 }
 
@@ -647,6 +708,10 @@ void do_reipl(void)
        case IPL_METHOD_FCP_RO_VM:
                __cpcmd("IPL", NULL, 0, NULL);
                break;
+       case IPL_METHOD_NSS:
+               sprintf(buf, "IPL %s", reipl_nss_name);
+               __cpcmd(buf, NULL, 0, NULL);
+               break;
        case IPL_METHOD_NONE:
        default:
                if (MACHINE_IS_VM)
@@ -733,6 +798,10 @@ static int __init ipl_init(void)
        case IPL_TYPE_FCP:
                rc = ipl_register_fcp_files();
                break;
+       case IPL_TYPE_NSS:
+               rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+                                       &ipl_nss_attr_group);
+               break;
        default:
                rc = sysfs_create_group(&ipl_subsys.kset.kobj,
                                        &ipl_unknown_attr_group);
@@ -755,6 +824,20 @@ static void __init reipl_probe(void)
        free_page((unsigned long)buffer);
 }
 
+static int __init reipl_nss_init(void)
+{
+       int rc;
+
+       if (!MACHINE_IS_VM)
+               return 0;
+       rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group);
+       if (rc)
+               return rc;
+       strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
+       reipl_capabilities |= IPL_TYPE_NSS;
+       return 0;
+}
+
 static int __init reipl_ccw_init(void)
 {
        int rc;
@@ -835,6 +918,9 @@ static int __init reipl_init(void)
        if (rc)
                return rc;
        rc = reipl_fcp_init();
+       if (rc)
+               return rc;
+       rc = reipl_nss_init();
        if (rc)
                return rc;
        rc = reipl_set_type(ipl_get_type());
@@ -993,8 +1079,6 @@ static void do_reset_calls(void)
                reset->fn();
 }
 
-extern void reset_mcck_handler(void);
-extern void reset_pgm_handler(void);
 extern __u32 dump_prefix_page;
 
 void s390_reset_system(void)
@@ -1016,14 +1100,14 @@ void s390_reset_system(void)
        __ctl_clear_bit(0,28);
 
        /* Set new machine check handler */
-       S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
+       S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
        S390_lowcore.mcck_new_psw.addr =
-               PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler;
+               PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
 
        /* Set new program check handler */
-       S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK;
+       S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK;
        S390_lowcore.program_new_psw.addr =
-               PSW_ADDR_AMODE | (unsigned long) &reset_pgm_handler;
+               PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
 
        do_reset_calls();
 }
index 1eef509186156d060dc48bf6931ae2505b688a21..8f0cbca3120318a497a268dca6e4ad946c461e3b 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *  arch/s390/kernel/irq.c
  *
- *  S390 version
- *    Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2004,2007
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *              Thomas Spatzier (tspat@de.ibm.com)
  *
  * This file contains interrupt related functions.
  */
@@ -14,6 +14,8 @@
 #include <linux/interrupt.h>
 #include <linux/seq_file.h>
 #include <linux/cpu.h>
+#include <linux/proc_fs.h>
+#include <linux/profile.h>
 
 /*
  * show_interrupts is needed by /proc/interrupts.
@@ -93,5 +95,12 @@ asmlinkage void do_softirq(void)
 
        local_irq_restore(flags);
 }
-
 EXPORT_SYMBOL(do_softirq);
+
+void init_irq_proc(void)
+{
+       struct proc_dir_entry *root_irq_dir;
+
+       root_irq_dir = proc_mkdir("irq", NULL);
+       create_prof_cpu_mask(root_irq_dir);
+}
index 576368c4f60585c4aa27fadea3fbd91e83327423..a466bab6677e15f506da1fb3d8168d5792170167 100644 (file)
@@ -155,15 +155,34 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
 static int __kprobes swap_instruction(void *aref)
 {
        struct ins_replace_args *args = aref;
+       u32 *addr;
+       u32 instr;
        int err = -EFAULT;
 
+       /*
+        * Text segment is read-only, hence we use stura to bypass dynamic
+        * address translation to exchange the instruction. Since stura
+        * always operates on four bytes, but we only want to exchange two
+        * bytes do some calculations to get things right. In addition we
+        * shall not cross any page boundaries (vmalloc area!) when writing
+        * the new instruction.
+        */
+       addr = (u32 *)ALIGN((unsigned long)args->ptr, 4);
+       if ((unsigned long)args->ptr & 2)
+               instr = ((*addr) & 0xffff0000) | args->new;
+       else
+               instr = ((*addr) & 0x0000ffff) | args->new << 16;
+
        asm volatile(
-               "0: mvc  0(2,%2),0(%3)\n"
-               "1: la   %0,0\n"
+               "       lra     %1,0(%1)\n"
+               "0:     stura   %2,%1\n"
+               "1:     la      %0,0\n"
                "2:\n"
                EX_TABLE(0b,2b)
-               : "+d" (err), "=m" (*args->ptr)
-               : "a" (args->ptr), "a" (&args->new), "m" (args->new));
+               : "+d" (err)
+               : "a" (addr), "d" (instr)
+               : "memory", "cc");
+
        return err;
 }
 
@@ -356,7 +375,7 @@ no_kprobe:
  *     - When the probed function returns, this probe
  *             causes the handlers to fire
  */
-void __kprobes kretprobe_trampoline_holder(void)
+void kretprobe_trampoline_holder(void)
 {
        asm volatile(".global kretprobe_trampoline\n"
                     "kretprobe_trampoline: bcr 0,0\n");
@@ -365,7 +384,8 @@ void __kprobes kretprobe_trampoline_holder(void)
 /*
  * Called when the probe at kretprobe trampoline is hit
  */
-int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes trampoline_probe_handler(struct kprobe *p,
+                                             struct pt_regs *regs)
 {
        struct kretprobe_instance *ri = NULL;
        struct hlist_head *head, empty_rp;
index f6d9bcc0f75bf2fdc017b924456ea10607628b46..52f57af252b443a43418d53ae65f0f59409dc8f9 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/mm.h>
 #include <linux/kexec.h>
 #include <linux/delay.h>
+#include <linux/reboot.h>
 #include <asm/cio.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
index d989ed45a7aafedc9bb2715671d052ebd909a102..39d1dd752529a3c345091b336d8819b1744fe5cb 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/moduleloader.h>
 
 #if 0
 #define DEBUGP printk
@@ -58,7 +59,7 @@ void module_free(struct module *mod, void *module_region)
            table entries. */
 }
 
-static inline void
+static void
 check_rela(Elf_Rela *rela, struct module *me)
 {
        struct mod_arch_syminfo *info;
@@ -181,7 +182,7 @@ apply_relocate(Elf_Shdr *sechdrs, const char *strtab, unsigned int symindex,
        return -ENOEXEC;
 }
 
-static inline int
+static int
 apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab, 
           struct module *me)
 {
index 6603fbb41d070d202a834b9ec4ef380775645663..5acfac654f9d7867463e4378b6e7e955bdc5b9ad 100644 (file)
@@ -144,7 +144,7 @@ static void default_idle(void)
 
        trace_hardirqs_on();
        /* Wait for external, I/O or machine check interrupt. */
-       __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT |
+       __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
                        PSW_MASK_IO | PSW_MASK_EXT);
 }
 
@@ -190,7 +190,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
        struct pt_regs regs;
 
        memset(&regs, 0, sizeof(regs));
-       regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT;
+       regs.psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
        regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
        regs.gprs[9] = (unsigned long) fn;
        regs.gprs[10] = (unsigned long) arg;
diff --git a/arch/s390/kernel/profile.c b/arch/s390/kernel/profile.c
deleted file mode 100644 (file)
index b81aa1f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/s390/kernel/profile.c
- *
- * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Thomas Spatzier (tspat@de.ibm.com)
- *
- */
-#include <linux/proc_fs.h>
-#include <linux/profile.h>
-
-static struct proc_dir_entry * root_irq_dir;
-
-void init_irq_proc(void)
-{
-       /* create /proc/irq */
-       root_irq_dir = proc_mkdir("irq", NULL);
-
-       /* create /proc/irq/prof_cpu_mask */
-       create_prof_cpu_mask(root_irq_dir);
-}
index 8f36504075ed0bf1239a605b56c293bb779f03cd..2a8f0872ea8b2dbd435f8b4879f8fce11d448187 100644 (file)
@@ -86,15 +86,13 @@ FixPerRegisters(struct task_struct *task)
                per_info->control_regs.bits.storage_alt_space_ctl = 0;
 }
 
-void
-set_single_step(struct task_struct *task)
+static void set_single_step(struct task_struct *task)
 {
        task->thread.per_info.single_step = 1;
        FixPerRegisters(task);
 }
 
-void
-clear_single_step(struct task_struct *task)
+static void clear_single_step(struct task_struct *task)
 {
        task->thread.per_info.single_step = 0;
        FixPerRegisters(task);
@@ -232,9 +230,9 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
                 */
                if (addr == (addr_t) &dummy->regs.psw.mask &&
 #ifdef CONFIG_COMPAT
-                   data != PSW_MASK_MERGE(PSW_USER32_BITS, data) &&
+                   data != PSW_MASK_MERGE(psw_user32_bits, data) &&
 #endif
-                   data != PSW_MASK_MERGE(PSW_USER_BITS, data))
+                   data != PSW_MASK_MERGE(psw_user_bits, data))
                        /* Invalid psw mask. */
                        return -EINVAL;
 #ifndef CONFIG_64BIT
@@ -309,7 +307,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
                copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
                if (copied != sizeof(tmp))
                        return -EIO;
-               return put_user(tmp, (unsigned long __user *) data);
+               return put_user(tmp, (unsigned long __force __user *) data);
 
        case PTRACE_PEEKUSR:
                /* read the word at location addr in the USER area. */
@@ -331,7 +329,7 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
 
        case PTRACE_PEEKUSR_AREA:
        case PTRACE_POKEUSR_AREA:
-               if (copy_from_user(&parea, (void __user *) addr,
+               if (copy_from_user(&parea, (void __force __user *) addr,
                                                        sizeof(parea)))
                        return -EFAULT;
                addr = parea.kernel_addr;
@@ -341,10 +339,11 @@ do_ptrace_normal(struct task_struct *child, long request, long addr, long data)
                        if (request == PTRACE_PEEKUSR_AREA)
                                ret = peek_user(child, addr, data);
                        else {
-                               addr_t tmp;
-                               if (get_user (tmp, (addr_t __user *) data))
+                               addr_t utmp;
+                               if (get_user(utmp,
+                                            (addr_t __force __user *) data))
                                        return -EFAULT;
-                               ret = poke_user(child, addr, tmp);
+                               ret = poke_user(child, addr, utmp);
                        }
                        if (ret)
                                return ret;
@@ -394,7 +393,7 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
                if (addr == (addr_t) &dummy32->regs.psw.mask) {
                        /* Fake a 31 bit psw mask. */
                        tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32);
-                       tmp = PSW32_MASK_MERGE(PSW32_USER_BITS, tmp);
+                       tmp = PSW32_MASK_MERGE(psw32_user_bits, tmp);
                } else if (addr == (addr_t) &dummy32->regs.psw.addr) {
                        /* Fake a 31 bit psw address. */
                        tmp = (__u32) task_pt_regs(child)->psw.addr |
@@ -469,11 +468,11 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
                 */
                if (addr == (addr_t) &dummy32->regs.psw.mask) {
                        /* Build a 64 bit psw mask from 31 bit mask. */
-                       if (tmp != PSW32_MASK_MERGE(PSW32_USER_BITS, tmp))
+                       if (tmp != PSW32_MASK_MERGE(psw32_user_bits, tmp))
                                /* Invalid psw mask. */
                                return -EINVAL;
                        task_pt_regs(child)->psw.mask =
-                               PSW_MASK_MERGE(PSW_USER32_BITS, (__u64) tmp << 32);
+                               PSW_MASK_MERGE(psw_user32_bits, (__u64) tmp << 32);
                } else if (addr == (addr_t) &dummy32->regs.psw.addr) {
                        /* Build a 64 bit psw address from 31 bit address. */
                        task_pt_regs(child)->psw.addr =
@@ -550,7 +549,7 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
                copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
                if (copied != sizeof(tmp))
                        return -EIO;
-               return put_user(tmp, (unsigned int __user *) data);
+               return put_user(tmp, (unsigned int __force __user *) data);
 
        case PTRACE_PEEKUSR:
                /* read the word at location addr in the USER area. */
@@ -571,7 +570,7 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
 
        case PTRACE_PEEKUSR_AREA:
        case PTRACE_POKEUSR_AREA:
-               if (copy_from_user(&parea, (void __user *) addr,
+               if (copy_from_user(&parea, (void __force __user *) addr,
                                                        sizeof(parea)))
                        return -EFAULT;
                addr = parea.kernel_addr;
@@ -581,10 +580,11 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
                        if (request == PTRACE_PEEKUSR_AREA)
                                ret = peek_user_emu31(child, addr, data);
                        else {
-                               __u32 tmp;
-                               if (get_user (tmp, (__u32 __user *) data))
+                               __u32 utmp;
+                               if (get_user(utmp,
+                                            (__u32 __force __user *) data))
                                        return -EFAULT;
-                               ret = poke_user_emu31(child, addr, tmp);
+                               ret = poke_user_emu31(child, addr, utmp);
                        }
                        if (ret)
                                return ret;
@@ -595,17 +595,19 @@ do_ptrace_emu31(struct task_struct *child, long request, long addr, long data)
                return 0;
        case PTRACE_GETEVENTMSG:
                return put_user((__u32) child->ptrace_message,
-                               (unsigned int __user *) data);
+                               (unsigned int __force __user *) data);
        case PTRACE_GETSIGINFO:
                if (child->last_siginfo == NULL)
                        return -EINVAL;
-               return copy_siginfo_to_user32((compat_siginfo_t __user *) data,
+               return copy_siginfo_to_user32((compat_siginfo_t
+                                              __force __user *) data,
                                              child->last_siginfo);
        case PTRACE_SETSIGINFO:
                if (child->last_siginfo == NULL)
                        return -EINVAL;
                return copy_siginfo_from_user32(child->last_siginfo,
-                                               (compat_siginfo_t __user *) data);
+                                               (compat_siginfo_t
+                                                __force __user *) data);
        }
        return ptrace_request(child, request, addr, data);
 }
diff --git a/arch/s390/kernel/reset.S b/arch/s390/kernel/reset.S
deleted file mode 100644 (file)
index 8a87355..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- *  arch/s390/kernel/reset.S
- *
- *    Copyright (C) IBM Corp. 2006
- *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
- *              Michael Holzheu <holzheu@de.ibm.com>
- */
-
-#include <asm/ptrace.h>
-#include <asm/lowcore.h>
-
-#ifdef CONFIG_64BIT
-
-       .globl  reset_mcck_handler
-reset_mcck_handler:
-       basr    %r13,0
-0:     lg      %r15,__LC_PANIC_STACK   # load panic stack
-       aghi    %r15,-STACK_FRAME_OVERHEAD
-       lg      %r1,s390_reset_mcck_handler-0b(%r13)
-       ltgr    %r1,%r1
-       jz      1f
-       basr    %r14,%r1
-1:     la      %r1,4095
-       lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
-       lpswe   __LC_MCK_OLD_PSW
-
-       .globl  s390_reset_mcck_handler
-s390_reset_mcck_handler:
-       .quad   0
-
-       .globl  reset_pgm_handler
-reset_pgm_handler:
-       stmg    %r0,%r15,__LC_SAVE_AREA
-       basr    %r13,0
-0:     lg      %r15,__LC_PANIC_STACK   # load panic stack
-       aghi    %r15,-STACK_FRAME_OVERHEAD
-       lg      %r1,s390_reset_pgm_handler-0b(%r13)
-       ltgr    %r1,%r1
-       jz      1f
-       basr    %r14,%r1
-       lmg     %r0,%r15,__LC_SAVE_AREA
-       lpswe   __LC_PGM_OLD_PSW
-1:     lpswe   disabled_wait_psw-0b(%r13)
-       .globl s390_reset_pgm_handler
-s390_reset_pgm_handler:
-       .quad   0
-       .align  8
-disabled_wait_psw:
-       .quad   0x0002000180000000,0x0000000000000000 + reset_pgm_handler
-
-#else /* CONFIG_64BIT */
-
-       .globl  reset_mcck_handler
-reset_mcck_handler:
-       basr    %r13,0
-0:     l       %r15,__LC_PANIC_STACK   # load panic stack
-       ahi     %r15,-STACK_FRAME_OVERHEAD
-       l       %r1,s390_reset_mcck_handler-0b(%r13)
-       ltr     %r1,%r1
-       jz      1f
-       basr    %r14,%r1
-1:     lm      %r0,%r15,__LC_GPREGS_SAVE_AREA
-       lpsw    __LC_MCK_OLD_PSW
-
-       .globl  s390_reset_mcck_handler
-s390_reset_mcck_handler:
-       .long   0
-
-       .globl  reset_pgm_handler
-reset_pgm_handler:
-       stm     %r0,%r15,__LC_SAVE_AREA
-       basr    %r13,0
-0:     l       %r15,__LC_PANIC_STACK   # load panic stack
-       ahi     %r15,-STACK_FRAME_OVERHEAD
-       l       %r1,s390_reset_pgm_handler-0b(%r13)
-       ltr     %r1,%r1
-       jz      1f
-       basr    %r14,%r1
-       lm      %r0,%r15,__LC_SAVE_AREA
-       lpsw    __LC_PGM_OLD_PSW
-
-1:     lpsw    disabled_wait_psw-0b(%r13)
-       .globl  s390_reset_pgm_handler
-s390_reset_pgm_handler:
-       .long   0
-disabled_wait_psw:
-       .align 8
-       .long   0x000a0000,0x00000000 + reset_pgm_handler
-
-#endif /* CONFIG_64BIT */
index bc5beaa8f98e13a0278dad9e612b9d41bef48383..acf93dba7727002e7507bf2e28bc4cb065e3763b 100644 (file)
@@ -125,14 +125,12 @@ void do_extint(struct pt_regs *regs, unsigned short code)
                 * Make sure that the i/o interrupt did not "overtake"
                 * the last HZ timer interrupt.
                 */
-               account_ticks();
+               account_ticks(S390_lowcore.int_clock);
        kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
         index = ext_hash(code);
        for (p = ext_int_hash[index]; p; p = p->next) {
-               if (likely(p->code == code)) {
-                       if (likely(p->handler))
-                               p->handler(code);
-               }
+               if (likely(p->code == code))
+                       p->handler(code);
        }
        irq_exit();
        set_irq_regs(old_regs);
index 5d8ee3baac147e0b153dab2d4ad0152ab22629f9..03739813d3bf4d7ba51fb44789f7763989286f6c 100644 (file)
@@ -38,6 +38,8 @@
 #include <linux/device.h>
 #include <linux/notifier.h>
 #include <linux/pfn.h>
+#include <linux/ctype.h>
+#include <linux/reboot.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
 #include <asm/sections.h>
+#include <asm/ebcdic.h>
+#include <asm/compat.h>
+
+long psw_kernel_bits   = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY |
+                          PSW_MASK_MCHECK | PSW_DEFAULT_KEY);
+long psw_user_bits     = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
+                          PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
+                          PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
 
 /*
  * User copy operations.
@@ -117,9 +127,9 @@ void __devinit cpu_init (void)
  */
 char vmhalt_cmd[128] = "";
 char vmpoff_cmd[128] = "";
-char vmpanic_cmd[128] = "";
+static char vmpanic_cmd[128] = "";
 
-static inline void strncpy_skip_quote(char *dst, char *src, int n)
+static void strncpy_skip_quote(char *dst, char *src, int n)
 {
         int sx, dx;
 
@@ -275,10 +285,6 @@ static void __init conmode_default(void)
 }
 
 #ifdef CONFIG_SMP
-extern void machine_restart_smp(char *);
-extern void machine_halt_smp(void);
-extern void machine_power_off_smp(void);
-
 void (*_machine_restart)(char *command) = machine_restart_smp;
 void (*_machine_halt)(void) = machine_halt_smp;
 void (*_machine_power_off)(void) = machine_power_off_smp;
@@ -386,6 +392,84 @@ static int __init early_parse_ipldelay(char *p)
 }
 early_param("ipldelay", early_parse_ipldelay);
 
+#ifdef CONFIG_S390_SWITCH_AMODE
+unsigned int switch_amode = 0;
+EXPORT_SYMBOL_GPL(switch_amode);
+
+static void set_amode_and_uaccess(unsigned long user_amode,
+                                 unsigned long user32_amode)
+{
+       psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode |
+                       PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
+                       PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
+#ifdef CONFIG_COMPAT
+       psw_user32_bits = PSW_BASE32_BITS | PSW_MASK_DAT | user_amode |
+                         PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
+                         PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
+       psw32_user_bits = PSW32_BASE_BITS | PSW32_MASK_DAT | user32_amode |
+                         PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
+                         PSW32_MASK_PSTATE;
+#endif
+       psw_kernel_bits = PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
+                         PSW_MASK_MCHECK | PSW_DEFAULT_KEY;
+
+       if (MACHINE_HAS_MVCOS) {
+               printk("mvcos available.\n");
+               memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess));
+       } else {
+               printk("mvcos not available.\n");
+               memcpy(&uaccess, &uaccess_pt, sizeof(uaccess));
+       }
+}
+
+/*
+ * Switch kernel/user addressing modes?
+ */
+static int __init early_parse_switch_amode(char *p)
+{
+       switch_amode = 1;
+       return 0;
+}
+early_param("switch_amode", early_parse_switch_amode);
+
+#else /* CONFIG_S390_SWITCH_AMODE */
+static inline void set_amode_and_uaccess(unsigned long user_amode,
+                                        unsigned long user32_amode)
+{
+}
+#endif /* CONFIG_S390_SWITCH_AMODE */
+
+#ifdef CONFIG_S390_EXEC_PROTECT
+unsigned int s390_noexec = 0;
+EXPORT_SYMBOL_GPL(s390_noexec);
+
+/*
+ * Enable execute protection?
+ */
+static int __init early_parse_noexec(char *p)
+{
+       if (!strncmp(p, "off", 3))
+               return 0;
+       switch_amode = 1;
+       s390_noexec = 1;
+       return 0;
+}
+early_param("noexec", early_parse_noexec);
+#endif /* CONFIG_S390_EXEC_PROTECT */
+
+static void setup_addressing_mode(void)
+{
+       if (s390_noexec) {
+               printk("S390 execute protection active, ");
+               set_amode_and_uaccess(PSW_ASC_SECONDARY, PSW32_ASC_SECONDARY);
+               return;
+       }
+       if (switch_amode) {
+               printk("S390 address spaces switched, ");
+               set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY);
+       }
+}
+
 static void __init
 setup_lowcore(void)
 {
@@ -402,19 +486,21 @@ setup_lowcore(void)
        lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY;
        lc->restart_psw.addr =
                PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
-       lc->external_new_psw.mask = PSW_KERNEL_BITS;
+       if (switch_amode)
+               lc->restart_psw.mask |= PSW_ASC_HOME;
+       lc->external_new_psw.mask = psw_kernel_bits;
        lc->external_new_psw.addr =
                PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
-       lc->svc_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_EXT;
+       lc->svc_new_psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT;
        lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
-       lc->program_new_psw.mask = PSW_KERNEL_BITS;
+       lc->program_new_psw.mask = psw_kernel_bits;
        lc->program_new_psw.addr =
                PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
        lc->mcck_new_psw.mask =
-               PSW_KERNEL_BITS & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
+               psw_kernel_bits & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
        lc->mcck_new_psw.addr =
                PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
-       lc->io_new_psw.mask = PSW_KERNEL_BITS;
+       lc->io_new_psw.mask = psw_kernel_bits;
        lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
        lc->ipl_device = S390_lowcore.ipl_device;
        lc->jiffy_timer = -1LL;
@@ -439,7 +525,7 @@ setup_lowcore(void)
 static void __init
 setup_resources(void)
 {
-       struct resource *res;
+       struct resource *res, *sub_res;
        int i;
 
        code_resource.start = (unsigned long) &_text;
@@ -464,8 +550,38 @@ setup_resources(void)
                res->start = memory_chunk[i].addr;
                res->end = memory_chunk[i].addr +  memory_chunk[i].size - 1;
                request_resource(&iomem_resource, res);
-               request_resource(res, &code_resource);
-               request_resource(res, &data_resource);
+
+               if (code_resource.start >= res->start  &&
+                       code_resource.start <= res->end &&
+                       code_resource.end > res->end) {
+                       sub_res = alloc_bootmem_low(sizeof(struct resource));
+                       memcpy(sub_res, &code_resource,
+                               sizeof(struct resource));
+                       sub_res->end = res->end;
+                       code_resource.start = res->end + 1;
+                       request_resource(res, sub_res);
+               }
+
+               if (code_resource.start >= res->start &&
+                       code_resource.start <= res->end &&
+                       code_resource.end <= res->end)
+                       request_resource(res, &code_resource);
+
+               if (data_resource.start >= res->start &&
+                       data_resource.start <= res->end &&
+                       data_resource.end > res->end) {
+                       sub_res = alloc_bootmem_low(sizeof(struct resource));
+                       memcpy(sub_res, &data_resource,
+                               sizeof(struct resource));
+                       sub_res->end = res->end;
+                       data_resource.start = res->end + 1;
+                       request_resource(res, sub_res);
+               }
+
+               if (data_resource.start >= res->start &&
+                       data_resource.start <= res->end &&
+                       data_resource.end <= res->end)
+                       request_resource(res, &data_resource);
        }
 }
 
@@ -495,16 +611,13 @@ static void __init setup_memory_end(void)
        }
        if (!memory_end)
                memory_end = memory_size;
-       if (real_size > memory_end)
-               printk("More memory detected than supported. Unused: %luk\n",
-                      (real_size - memory_end) >> 10);
 }
 
 static void __init
 setup_memory(void)
 {
         unsigned long bootmap_size;
-       unsigned long start_pfn, end_pfn, init_pfn;
+       unsigned long start_pfn, end_pfn;
        int i;
 
        /*
@@ -514,10 +627,6 @@ setup_memory(void)
        start_pfn = PFN_UP(__pa(&_end));
        end_pfn = max_pfn = PFN_DOWN(memory_end);
 
-       /* Initialize storage key for kernel pages */
-       for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++)
-               page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY);
-
 #ifdef CONFIG_BLK_DEV_INITRD
        /*
         * Move the initrd in case the bitmap of the bootmem allocater
@@ -651,6 +760,7 @@ setup_arch(char **cmdline_p)
        parse_early_param();
 
        setup_memory_end();
+       setup_addressing_mode();
        setup_memory();
        setup_resources();
        setup_lowcore();
@@ -694,6 +804,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
         struct cpuinfo_S390 *cpuinfo;
        unsigned long n = (unsigned long) v - 1;
 
+       s390_adjust_jiffies();
        preempt_disable();
        if (!n) {
                seq_printf(m, "vendor_id       : IBM/S390\n"
index 4c8a7954ef48b28274cdf61833e9f31609f2ff70..554f9cf7499c9236209e9ebbac7bb866d5b7100a 100644 (file)
@@ -119,7 +119,7 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
 
        /* Copy a 'clean' PSW mask to the user to avoid leaking
           information about whether PER is currently on.  */
-       user_sregs.regs.psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask);
+       user_sregs.regs.psw.mask = PSW_MASK_MERGE(psw_user_bits, regs->psw.mask);
        user_sregs.regs.psw.addr = regs->psw.addr;
        memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
        memcpy(&user_sregs.regs.acrs, current->thread.acrs,
index c0cd255fddbd04ccce6895bac1cd08b940be8535..65b52320d145661f245f836318d51b7bfb71a317 100644 (file)
 
 #include <linux/module.h>
 #include <linux/init.h>
-
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/kernel_stat.h>
 #include <linux/smp_lock.h>
-
 #include <linux/delay.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
 #include <linux/cpu.h>
-
+#include <linux/timex.h>
+#include <asm/setup.h>
 #include <asm/sigp.h>
 #include <asm/pgalloc.h>
 #include <asm/irq.h>
 #include <asm/s390_ext.h>
 #include <asm/cpcmd.h>
 #include <asm/tlbflush.h>
+#include <asm/timer.h>
 
 extern volatile int __cpu_logical_map[];
 
@@ -53,12 +53,6 @@ cpumask_t cpu_possible_map = CPU_MASK_NONE;
 
 static struct task_struct *current_set[NR_CPUS];
 
-/*
- * Reboot, halt and power_off routines for SMP.
- */
-extern char vmhalt_cmd[];
-extern char vmpoff_cmd[];
-
 static void smp_ext_bitcall(int, ec_bit_sig);
 static void smp_ext_bitcall_others(ec_bit_sig);
 
@@ -200,7 +194,7 @@ int smp_call_function_on(void (*func) (void *info), void *info,
 }
 EXPORT_SYMBOL(smp_call_function_on);
 
-static inline void do_send_stop(void)
+static void do_send_stop(void)
 {
         int cpu, rc;
 
@@ -214,7 +208,7 @@ static inline void do_send_stop(void)
        }
 }
 
-static inline void do_store_status(void)
+static void do_store_status(void)
 {
         int cpu, rc;
 
@@ -230,7 +224,7 @@ static inline void do_store_status(void)
         }
 }
 
-static inline void do_wait_for_stop(void)
+static void do_wait_for_stop(void)
 {
        int cpu;
 
@@ -250,7 +244,7 @@ static inline void do_wait_for_stop(void)
 void smp_send_stop(void)
 {
        /* Disable all interrupts/machine checks */
-       __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK);
+       __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
 
         /* write magic number to zero page (absolute 0) */
        lowcore_ptr[smp_processor_id()]->panic_magic = __PANIC_MAGIC;
@@ -298,7 +292,7 @@ void machine_power_off_smp(void)
  * cpus are handled.
  */
 
-void do_ext_call_interrupt(__u16 code)
+static void do_ext_call_interrupt(__u16 code)
 {
         unsigned long bits;
 
@@ -385,7 +379,7 @@ struct ec_creg_mask_parms {
 /*
  * callback for setting/clearing control bits
  */
-void smp_ctl_bit_callback(void *info) {
+static void smp_ctl_bit_callback(void *info) {
        struct ec_creg_mask_parms *pp = info;
        unsigned long cregs[16];
        int i;
@@ -458,17 +452,15 @@ __init smp_count_cpus(void)
 /*
  *      Activate a secondary processor.
  */
-extern void init_cpu_timer(void);
-extern void init_cpu_vtimer(void);
-
 int __devinit start_secondary(void *cpuvoid)
 {
         /* Setup the cpu */
         cpu_init();
        preempt_disable();
-        /* init per CPU timer */
+       /* Enable TOD clock interrupts on the secondary cpu. */
         init_cpu_timer();
 #ifdef CONFIG_VIRT_TIMER
+       /* Enable cpu timer interrupts on the secondary cpu. */
         init_cpu_vtimer();
 #endif
        /* Enable pfault pseudo page faults on this cpu. */
@@ -542,7 +534,7 @@ smp_put_cpu(int cpu)
        spin_unlock_irqrestore(&smp_reserve_lock, flags);
 }
 
-static inline int
+static int
 cpu_stopped(int cpu)
 {
        __u32 status;
index 0d14a4789bf2e1a781e8ac98a42c3ef1e6eed09a..2e5c65a1863eaada4750a1c36ed0baa3ff3be5ea 100644 (file)
 #include <linux/stacktrace.h>
 #include <linux/kallsyms.h>
 
-static inline unsigned long save_context_stack(struct stack_trace *trace,
-                                              unsigned int *skip,
-                                              unsigned long sp,
-                                              unsigned long low,
-                                              unsigned long high)
+static unsigned long save_context_stack(struct stack_trace *trace,
+                                       unsigned int *skip,
+                                       unsigned long sp,
+                                       unsigned long low,
+                                       unsigned long high)
 {
        struct stack_frame *sf;
        struct pt_regs *regs;
index 6cceed4df73ee40adf6f233d601ae511df9050bc..3b91f27ab202862e28ae2b10ef5f48e87cadb0c6 100644 (file)
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
 #include <asm/timer.h>
+#include <asm/etr.h>
 
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY     ((unsigned long) 1000000/HZ)
 #define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
 
+/* The value of the TOD clock for 1.1.1970. */
+#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
+
 /*
  * Create a small time difference between the timer interrupts
  * on the different cpus to avoid lock contention.
@@ -51,6 +55,7 @@
 #define TICK_SIZE tick
 
 static ext_int_info_t ext_int_info_cc;
+static ext_int_info_t ext_int_etr_cc;
 static u64 init_timer_cc;
 static u64 jiffies_timer_cc;
 static u64 xtime_cc;
@@ -89,29 +94,21 @@ void tod_to_timeval(__u64 todval, struct timespec *xtime)
 #define s390_do_profile()      do { ; } while(0)
 #endif /* CONFIG_PROFILING */
 
-
 /*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * Advance the per cpu tick counter up to the time given with the
+ * "time" argument. The per cpu update consists of accounting
+ * the virtual cpu time, calling update_process_times and calling
+ * the profiling hook. If xtime is before time it is advanced as well.
  */
-void account_ticks(void)
+void account_ticks(u64 time)
 {
-       __u64 tmp;
        __u32 ticks;
+       __u64 tmp;
 
        /* Calculate how many ticks have passed. */
-       if (S390_lowcore.int_clock < S390_lowcore.jiffy_timer) {
-               /*
-                * We have to program the clock comparator even if
-                * no tick has passed. That happens if e.g. an i/o
-                * interrupt wakes up an idle processor that has
-                * switched off its hz timer.
-                */
-               tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION;
-               asm volatile ("SCKC %0" : : "m" (tmp));
+       if (time < S390_lowcore.jiffy_timer)
                return;
-       }
-       tmp = S390_lowcore.int_clock - S390_lowcore.jiffy_timer;
+       tmp = time - S390_lowcore.jiffy_timer;
        if (tmp >= 2*CLK_TICKS_PER_JIFFY) {  /* more than two ticks ? */
                ticks = __div(tmp, CLK_TICKS_PER_JIFFY) + 1;
                S390_lowcore.jiffy_timer +=
@@ -124,10 +121,6 @@ void account_ticks(void)
                S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
        }
 
-       /* set clock comparator for next tick */
-       tmp = S390_lowcore.jiffy_timer + CPU_DEVIATION;
-        asm volatile ("SCKC %0" : : "m" (tmp));
-
 #ifdef CONFIG_SMP
        /*
         * Do not rely on the boot cpu to do the calls to do_timer.
@@ -173,7 +166,7 @@ int sysctl_hz_timer = 1;
  * Stop the HZ tick on the current CPU.
  * Only cpu_idle may call this function.
  */
-static inline void stop_hz_timer(void)
+static void stop_hz_timer(void)
 {
        unsigned long flags;
        unsigned long seq, next;
@@ -210,20 +203,21 @@ static inline void stop_hz_timer(void)
                if (timer >= jiffies_timer_cc)
                        todval = timer;
        }
-       asm volatile ("SCKC %0" : : "m" (todval));
+       set_clock_comparator(todval);
 }
 
 /*
  * Start the HZ tick on the current CPU.
  * Only cpu_idle may call this function.
  */
-static inline void start_hz_timer(void)
+static void start_hz_timer(void)
 {
        BUG_ON(!in_interrupt());
 
        if (!cpu_isset(smp_processor_id(), nohz_cpu_mask))
                return;
-       account_ticks();
+       account_ticks(get_clock());
+       set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
        cpu_clear(smp_processor_id(), nohz_cpu_mask);
 }
 
@@ -245,7 +239,7 @@ static struct notifier_block nohz_idle_nb = {
        .notifier_call = nohz_idle_notify,
 };
 
-void __init nohz_init(void)
+static void __init nohz_init(void)
 {
        if (register_idle_notifier(&nohz_idle_nb))
                panic("Couldn't register idle notifier");
@@ -254,24 +248,57 @@ void __init nohz_init(void)
 #endif
 
 /*
- * Start the clock comparator on the current CPU.
+ * Set up per cpu jiffy timer and set the clock comparator.
+ */
+static void setup_jiffy_timer(void)
+{
+       /* Set up clock comparator to next jiffy. */
+       S390_lowcore.jiffy_timer =
+               jiffies_timer_cc + (jiffies_64 + 1) * CLK_TICKS_PER_JIFFY;
+       set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+}
+
+/*
+ * Set up lowcore and control register of the current cpu to
+ * enable TOD clock and clock comparator interrupts.
  */
 void init_cpu_timer(void)
 {
-       unsigned long cr0;
-       __u64 timer;
+       setup_jiffy_timer();
 
-       timer = jiffies_timer_cc + jiffies_64 * CLK_TICKS_PER_JIFFY;
-       S390_lowcore.jiffy_timer = timer + CLK_TICKS_PER_JIFFY;
-       timer += CLK_TICKS_PER_JIFFY + CPU_DEVIATION;
-       asm volatile ("SCKC %0" : : "m" (timer));
-        /* allow clock comparator timer interrupt */
-       __ctl_store(cr0, 0, 0);
-        cr0 |= 0x800;
-       __ctl_load(cr0, 0, 0);
+       /* Enable clock comparator timer interrupt. */
+       __ctl_set_bit(0,11);
+
+       /* Always allow ETR external interrupts, even without an ETR. */
+       __ctl_set_bit(0, 4);
 }
 
-extern void vtime_init(void);
+static void clock_comparator_interrupt(__u16 code)
+{
+       /* set clock comparator for next tick */
+       set_clock_comparator(S390_lowcore.jiffy_timer + CPU_DEVIATION);
+}
+
+static void etr_reset(void);
+static void etr_init(void);
+static void etr_ext_handler(__u16);
+
+/*
+ * Get the TOD clock running.
+ */
+static u64 __init reset_tod_clock(void)
+{
+       u64 time;
+
+       etr_reset();
+       if (store_clock(&time) == 0)
+               return time;
+       /* TOD clock not running. Set the clock to Unix Epoch. */
+       if (set_clock(TOD_UNIX_EPOCH) != 0 || store_clock(&time) != 0)
+               panic("TOD clock not operational.");
+
+       return TOD_UNIX_EPOCH;
+}
 
 static cycle_t read_tod_clock(void)
 {
@@ -295,48 +322,31 @@ static struct clocksource clocksource_tod = {
  */
 void __init time_init(void)
 {
-       __u64 set_time_cc;
-       int cc;
-
-        /* kick the TOD clock */
-       asm volatile(
-               "       stck    0(%2)\n"
-               "       ipm     %0\n"
-               "       srl     %0,28"
-               : "=d" (cc), "=m" (init_timer_cc)
-               : "a" (&init_timer_cc) : "cc");
-        switch (cc) {
-        case 0: /* clock in set state: all is fine */
-                break;
-        case 1: /* clock in non-set state: FIXME */
-                printk("time_init: TOD clock in non-set state\n");
-                break;
-        case 2: /* clock in error state: FIXME */
-                printk("time_init: TOD clock in error state\n");
-                break;
-        case 3: /* clock in stopped or not-operational state: FIXME */
-                printk("time_init: TOD clock stopped/non-operational\n");
-                break;
-        }
+       init_timer_cc = reset_tod_clock();
+       xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
        jiffies_timer_cc = init_timer_cc - jiffies_64 * CLK_TICKS_PER_JIFFY;
 
        /* set xtime */
-       xtime_cc = init_timer_cc + CLK_TICKS_PER_JIFFY;
-       set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
-               (0x3c26700LL*1000000*4096);
-        tod_to_timeval(set_time_cc, &xtime);
+       tod_to_timeval(init_timer_cc - TOD_UNIX_EPOCH, &xtime);
         set_normalized_timespec(&wall_to_monotonic,
                                 -xtime.tv_sec, -xtime.tv_nsec);
 
        /* request the clock comparator external interrupt */
-       if (register_early_external_interrupt(0x1004, NULL,
+       if (register_early_external_interrupt(0x1004,
+                                             clock_comparator_interrupt,
                                              &ext_int_info_cc) != 0)
                 panic("Couldn't request external interrupt 0x1004");
 
        if (clocksource_register(&clocksource_tod) != 0)
                panic("Could not register TOD clock source");
 
-        init_cpu_timer();
+       /* request the etr external interrupt */
+       if (register_early_external_interrupt(0x1406, etr_ext_handler,
+                                             &ext_int_etr_cc) != 0)
+               panic("Couldn't request external interrupt 0x1406");
+
+       /* Enable TOD clock interrupts on the boot cpu. */
+       init_cpu_timer();
 
 #ifdef CONFIG_NO_IDLE_HZ
        nohz_init();
@@ -345,5 +355,1048 @@ void __init time_init(void)
 #ifdef CONFIG_VIRT_TIMER
        vtime_init();
 #endif
+       etr_init();
+}
+
+/*
+ * External Time Reference (ETR) code.
+ */
+static int etr_port0_online;
+static int etr_port1_online;
+
+static int __init early_parse_etr(char *p)
+{
+       if (strncmp(p, "off", 3) == 0)
+               etr_port0_online = etr_port1_online = 0;
+       else if (strncmp(p, "port0", 5) == 0)
+               etr_port0_online = 1;
+       else if (strncmp(p, "port1", 5) == 0)
+               etr_port1_online = 1;
+       else if (strncmp(p, "on", 2) == 0)
+               etr_port0_online = etr_port1_online = 1;
+       return 0;
+}
+early_param("etr", early_parse_etr);
+
+enum etr_event {
+       ETR_EVENT_PORT0_CHANGE,
+       ETR_EVENT_PORT1_CHANGE,
+       ETR_EVENT_PORT_ALERT,
+       ETR_EVENT_SYNC_CHECK,
+       ETR_EVENT_SWITCH_LOCAL,
+       ETR_EVENT_UPDATE,
+};
+
+enum etr_flags {
+       ETR_FLAG_ENOSYS,
+       ETR_FLAG_EACCES,
+       ETR_FLAG_STEAI,
+};
+
+/*
+ * Valid bit combinations of the eacr register are (x = don't care):
+ * e0 e1 dp p0 p1 ea es sl
+ *  0  0  x  0 0  0  0  0  initial, disabled state
+ *  0  0  x  0 1  1  0  0  port 1 online
+ *  0  0  x  1 0  1  0  0  port 0 online
+ *  0  0  x  1 1  1  0  0  both ports online
+ *  0  1  x  0 1  1  0  0  port 1 online and usable, ETR or PPS mode
+ *  0  1  x  0 1  1  0  1  port 1 online, usable and ETR mode
+ *  0  1  x  0 1  1  1  0  port 1 online, usable, PPS mode, in-sync
+ *  0  1  x  0 1  1  1  1  port 1 online, usable, ETR mode, in-sync
+ *  0  1  x  1 1  1  0  0  both ports online, port 1 usable
+ *  0  1  x  1 1  1  1  0  both ports online, port 1 usable, PPS mode, in-sync
+ *  0  1  x  1 1  1  1  1  both ports online, port 1 usable, ETR mode, in-sync
+ *  1  0  x  1 0  1  0  0  port 0 online and usable, ETR or PPS mode
+ *  1  0  x  1 0  1  0  1  port 0 online, usable and ETR mode
+ *  1  0  x  1 0  1  1  0  port 0 online, usable, PPS mode, in-sync
+ *  1  0  x  1 0  1  1  1  port 0 online, usable, ETR mode, in-sync
+ *  1  0  x  1 1  1  0  0  both ports online, port 0 usable
+ *  1  0  x  1 1  1  1  0  both ports online, port 0 usable, PPS mode, in-sync
+ *  1  0  x  1 1  1  1  1  both ports online, port 0 usable, ETR mode, in-sync
+ *  1  1  x  1 1  1  1  0  both ports online & usable, ETR, in-sync
+ *  1  1  x  1 1  1  1  1  both ports online & usable, ETR, in-sync
+ */
+static struct etr_eacr etr_eacr;
+static u64 etr_tolec;                  /* time of last eacr update */
+static unsigned long etr_flags;
+static struct etr_aib etr_port0;
+static int etr_port0_uptodate;
+static struct etr_aib etr_port1;
+static int etr_port1_uptodate;
+static unsigned long etr_events;
+static struct timer_list etr_timer;
+static struct tasklet_struct etr_tasklet;
+static DEFINE_PER_CPU(atomic_t, etr_sync_word);
+
+static void etr_timeout(unsigned long dummy);
+static void etr_tasklet_fn(unsigned long dummy);
+
+/*
+ * The etr get_clock function. It will write the current clock value
+ * to the clock pointer and return 0 if the clock is in sync with the
+ * external time source. If the clock mode is local it will return
+ * -ENOSYS and -EAGAIN if the clock is not in sync with the external
+ * reference. This function is what ETR is all about..
+ */
+int get_sync_clock(unsigned long long *clock)
+{
+       atomic_t *sw_ptr;
+       unsigned int sw0, sw1;
+
+       sw_ptr = &get_cpu_var(etr_sync_word);
+       sw0 = atomic_read(sw_ptr);
+       *clock = get_clock();
+       sw1 = atomic_read(sw_ptr);
+       put_cpu_var(etr_sync_sync);
+       if (sw0 == sw1 && (sw0 & 0x80000000U))
+               /* Success: time is in sync. */
+               return 0;
+       if (test_bit(ETR_FLAG_ENOSYS, &etr_flags))
+               return -ENOSYS;
+       if (test_bit(ETR_FLAG_EACCES, &etr_flags))
+               return -EACCES;
+       return -EAGAIN;
+}
+EXPORT_SYMBOL(get_sync_clock);
+
+/*
+ * Make get_sync_clock return -EAGAIN.
+ */
+static void etr_disable_sync_clock(void *dummy)
+{
+       atomic_t *sw_ptr = &__get_cpu_var(etr_sync_word);
+       /*
+        * Clear the in-sync bit 2^31. All get_sync_clock calls will
+        * fail until the sync bit is turned back on. In addition
+        * increase the "sequence" counter to avoid the race of an
+        * etr event and the complete recovery against get_sync_clock.
+        */
+       atomic_clear_mask(0x80000000, sw_ptr);
+       atomic_inc(sw_ptr);
+}
+
+/*
+ * Make get_sync_clock return 0 again.
+ * Needs to be called from a context disabled for preemption.
+ */
+static void etr_enable_sync_clock(void)
+{
+       atomic_t *sw_ptr = &__get_cpu_var(etr_sync_word);
+       atomic_set_mask(0x80000000, sw_ptr);
+}
+
+/*
+ * Reset ETR attachment.
+ */
+static void etr_reset(void)
+{
+       etr_eacr =  (struct etr_eacr) {
+               .e0 = 0, .e1 = 0, ._pad0 = 4, .dp = 0,
+               .p0 = 0, .p1 = 0, ._pad1 = 0, .ea = 0,
+               .es = 0, .sl = 0 };
+       if (etr_setr(&etr_eacr) == 0)
+               etr_tolec = get_clock();
+       else {
+               set_bit(ETR_FLAG_ENOSYS, &etr_flags);
+               if (etr_port0_online || etr_port1_online) {
+                       printk(KERN_WARNING "Running on non ETR capable "
+                              "machine, only local mode available.\n");
+                       etr_port0_online = etr_port1_online = 0;
+               }
+       }
+}
+
+static void etr_init(void)
+{
+       struct etr_aib aib;
+
+       if (test_bit(ETR_FLAG_ENOSYS, &etr_flags))
+               return;
+       /* Check if this machine has the steai instruction. */
+       if (etr_steai(&aib, ETR_STEAI_STEPPING_PORT) == 0)
+               set_bit(ETR_FLAG_STEAI, &etr_flags);
+       setup_timer(&etr_timer, etr_timeout, 0UL);
+       tasklet_init(&etr_tasklet, etr_tasklet_fn, 0);
+       if (!etr_port0_online && !etr_port1_online)
+               set_bit(ETR_FLAG_EACCES, &etr_flags);
+       if (etr_port0_online) {
+               set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
+               tasklet_hi_schedule(&etr_tasklet);
+       }
+       if (etr_port1_online) {
+               set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
+               tasklet_hi_schedule(&etr_tasklet);
+       }
+}
+
+/*
+ * Two sorts of ETR machine checks. The architecture reads:
+ * "When a machine-check niterruption occurs and if a switch-to-local or
+ *  ETR-sync-check interrupt request is pending but disabled, this pending
+ *  disabled interruption request is indicated and is cleared".
+ * Which means that we can get etr_switch_to_local events from the machine
+ * check handler although the interruption condition is disabled. Lovely..
+ */
+
+/*
+ * Switch to local machine check. This is called when the last usable
+ * ETR port goes inactive. After switch to local the clock is not in sync.
+ */
+void etr_switch_to_local(void)
+{
+       if (!etr_eacr.sl)
+               return;
+       etr_disable_sync_clock(NULL);
+       set_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events);
+       tasklet_hi_schedule(&etr_tasklet);
+}
+
+/*
+ * ETR sync check machine check. This is called when the ETR OTE and the
+ * local clock OTE are farther apart than the ETR sync check tolerance.
+ * After a ETR sync check the clock is not in sync. The machine check
+ * is broadcasted to all cpus at the same time.
+ */
+void etr_sync_check(void)
+{
+       if (!etr_eacr.es)
+               return;
+       etr_disable_sync_clock(NULL);
+       set_bit(ETR_EVENT_SYNC_CHECK, &etr_events);
+       tasklet_hi_schedule(&etr_tasklet);
+}
+
+/*
+ * ETR external interrupt. There are two causes:
+ * 1) port state change, check the usability of the port
+ * 2) port alert, one of the ETR-data-validity bits (v1-v2 bits of the
+ *    sldr-status word) or ETR-data word 1 (edf1) or ETR-data word 3 (edf3)
+ *    or ETR-data word 4 (edf4) has changed.
+ */
+static void etr_ext_handler(__u16 code)
+{
+       struct etr_interruption_parameter *intparm =
+               (struct etr_interruption_parameter *) &S390_lowcore.ext_params;
+
+       if (intparm->pc0)
+               /* ETR port 0 state change. */
+               set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
+       if (intparm->pc1)
+               /* ETR port 1 state change. */
+               set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
+       if (intparm->eai)
+               /*
+                * ETR port alert on either port 0, 1 or both.
+                * Both ports are not up-to-date now.
+                */
+               set_bit(ETR_EVENT_PORT_ALERT, &etr_events);
+       tasklet_hi_schedule(&etr_tasklet);
+}
+
+static void etr_timeout(unsigned long dummy)
+{
+       set_bit(ETR_EVENT_UPDATE, &etr_events);
+       tasklet_hi_schedule(&etr_tasklet);
+}
+
+/*
+ * Check if the etr mode is pss.
+ */
+static inline int etr_mode_is_pps(struct etr_eacr eacr)
+{
+       return eacr.es && !eacr.sl;
+}
+
+/*
+ * Check if the etr mode is etr.
+ */
+static inline int etr_mode_is_etr(struct etr_eacr eacr)
+{
+       return eacr.es && eacr.sl;
+}
+
+/*
+ * Check if the port can be used for TOD synchronization.
+ * For PPS mode the port has to receive OTEs. For ETR mode
+ * the port has to receive OTEs, the ETR stepping bit has to
+ * be zero and the validity bits for data frame 1, 2, and 3
+ * have to be 1.
+ */
+static int etr_port_valid(struct etr_aib *aib, int port)
+{
+       unsigned int psc;
+
+       /* Check that this port is receiving OTEs. */
+       if (aib->tsp == 0)
+               return 0;
+
+       psc = port ? aib->esw.psc1 : aib->esw.psc0;
+       if (psc == etr_lpsc_pps_mode)
+               return 1;
+       if (psc == etr_lpsc_operational_step)
+               return !aib->esw.y && aib->slsw.v1 &&
+                       aib->slsw.v2 && aib->slsw.v3;
+       return 0;
+}
+
+/*
+ * Check if two ports are on the same network.
+ */
+static int etr_compare_network(struct etr_aib *aib1, struct etr_aib *aib2)
+{
+       // FIXME: any other fields we have to compare?
+       return aib1->edf1.net_id == aib2->edf1.net_id;
+}
+
+/*
+ * Wrapper for etr_stei that converts physical port states
+ * to logical port states to be consistent with the output
+ * of stetr (see etr_psc vs. etr_lpsc).
+ */
+static void etr_steai_cv(struct etr_aib *aib, unsigned int func)
+{
+       BUG_ON(etr_steai(aib, func) != 0);
+       /* Convert port state to logical port state. */
+       if (aib->esw.psc0 == 1)
+               aib->esw.psc0 = 2;
+       else if (aib->esw.psc0 == 0 && aib->esw.p == 0)
+               aib->esw.psc0 = 1;
+       if (aib->esw.psc1 == 1)
+               aib->esw.psc1 = 2;
+       else if (aib->esw.psc1 == 0 && aib->esw.p == 1)
+               aib->esw.psc1 = 1;
+}
+
+/*
+ * Check if the aib a2 is still connected to the same attachment as
+ * aib a1, the etv values differ by one and a2 is valid.
+ */
+static int etr_aib_follows(struct etr_aib *a1, struct etr_aib *a2, int p)
+{
+       int state_a1, state_a2;
+
+       /* Paranoia check: e0/e1 should better be the same. */
+       if (a1->esw.eacr.e0 != a2->esw.eacr.e0 ||
+           a1->esw.eacr.e1 != a2->esw.eacr.e1)
+               return 0;
+
+       /* Still connected to the same etr ? */
+       state_a1 = p ? a1->esw.psc1 : a1->esw.psc0;
+       state_a2 = p ? a2->esw.psc1 : a2->esw.psc0;
+       if (state_a1 == etr_lpsc_operational_step) {
+               if (state_a2 != etr_lpsc_operational_step ||
+                   a1->edf1.net_id != a2->edf1.net_id ||
+                   a1->edf1.etr_id != a2->edf1.etr_id ||
+                   a1->edf1.etr_pn != a2->edf1.etr_pn)
+                       return 0;
+       } else if (state_a2 != etr_lpsc_pps_mode)
+               return 0;
+
+       /* The ETV value of a2 needs to be ETV of a1 + 1. */
+       if (a1->edf2.etv + 1 != a2->edf2.etv)
+               return 0;
+
+       if (!etr_port_valid(a2, p))
+               return 0;
+
+       return 1;
+}
+
+/*
+ * The time is "clock". xtime is what we think the time is.
+ * Adjust the value by a multiple of jiffies and add the delta to ntp.
+ * "delay" is an approximation how long the synchronization took. If
+ * the time correction is positive, then "delay" is subtracted from
+ * the time difference and only the remaining part is passed to ntp.
+ */
+static void etr_adjust_time(unsigned long long clock, unsigned long long delay)
+{
+       unsigned long long delta, ticks;
+       struct timex adjust;
+
+       /*
+        * We don't have to take the xtime lock because the cpu
+        * executing etr_adjust_time is running disabled in
+        * tasklet context and all other cpus are looping in
+        * etr_sync_cpu_start.
+        */
+       if (clock > xtime_cc) {
+               /* It is later than we thought. */
+               delta = ticks = clock - xtime_cc;
+               delta = ticks = (delta < delay) ? 0 : delta - delay;
+               delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+               init_timer_cc = init_timer_cc + delta;
+               jiffies_timer_cc = jiffies_timer_cc + delta;
+               xtime_cc = xtime_cc + delta;
+               adjust.offset = ticks * (1000000 / HZ);
+       } else {
+               /* It is earlier than we thought. */
+               delta = ticks = xtime_cc - clock;
+               delta -= do_div(ticks, CLK_TICKS_PER_JIFFY);
+               init_timer_cc = init_timer_cc - delta;
+               jiffies_timer_cc = jiffies_timer_cc - delta;
+               xtime_cc = xtime_cc - delta;
+               adjust.offset = -ticks * (1000000 / HZ);
+       }
+       if (adjust.offset != 0) {
+               printk(KERN_NOTICE "etr: time adjusted by %li micro-seconds\n",
+                      adjust.offset);
+               adjust.modes = ADJ_OFFSET_SINGLESHOT;
+               do_adjtimex(&adjust);
+       }
+}
+
+static void etr_sync_cpu_start(void *dummy)
+{
+       int *in_sync = dummy;
+
+       etr_enable_sync_clock();
+       /*
+        * This looks like a busy wait loop but it isn't. etr_sync_cpus
+        * is called on all other cpus while the TOD clocks is stopped.
+        * __udelay will stop the cpu on an enabled wait psw until the
+        * TOD is running again.
+        */
+       while (*in_sync == 0)
+               __udelay(1);
+       if (*in_sync != 1)
+               /* Didn't work. Clear per-cpu in sync bit again. */
+               etr_disable_sync_clock(NULL);
+       /*
+        * This round of TOD syncing is done. Set the clock comparator
+        * to the next tick and let the processor continue.
+        */
+       setup_jiffy_timer();
+}
+
+static void etr_sync_cpu_end(void *dummy)
+{
+}
+
+/*
+ * Sync the TOD clock using the port refered to by aibp. This port
+ * has to be enabled and the other port has to be disabled. The
+ * last eacr update has to be more than 1.6 seconds in the past.
+ */
+static int etr_sync_clock(struct etr_aib *aib, int port)
+{
+       struct etr_aib *sync_port;
+       unsigned long long clock, delay;
+       int in_sync, follows;
+       int rc;
+
+       /* Check if the current aib is adjacent to the sync port aib. */
+       sync_port = (port == 0) ? &etr_port0 : &etr_port1;
+       follows = etr_aib_follows(sync_port, aib, port);
+       memcpy(sync_port, aib, sizeof(*aib));
+       if (!follows)
+               return -EAGAIN;
+
+       /*
+        * Catch all other cpus and make them wait until we have
+        * successfully synced the clock. smp_call_function will
+        * return after all other cpus are in etr_sync_cpu_start.
+        */
+       in_sync = 0;
+       preempt_disable();
+       smp_call_function(etr_sync_cpu_start,&in_sync,0,0);
+       local_irq_disable();
+       etr_enable_sync_clock();
+
+       /* Set clock to next OTE. */
+       __ctl_set_bit(14, 21);
+       __ctl_set_bit(0, 29);
+       clock = ((unsigned long long) (aib->edf2.etv + 1)) << 32;
+       if (set_clock(clock) == 0) {
+               __udelay(1);    /* Wait for the clock to start. */
+               __ctl_clear_bit(0, 29);
+               __ctl_clear_bit(14, 21);
+               etr_stetr(aib);
+               /* Adjust Linux timing variables. */
+               delay = (unsigned long long)
+                       (aib->edf2.etv - sync_port->edf2.etv) << 32;
+               etr_adjust_time(clock, delay);
+               setup_jiffy_timer();
+               /* Verify that the clock is properly set. */
+               if (!etr_aib_follows(sync_port, aib, port)) {
+                       /* Didn't work. */
+                       etr_disable_sync_clock(NULL);
+                       in_sync = -EAGAIN;
+                       rc = -EAGAIN;
+               } else {
+                       in_sync = 1;
+                       rc = 0;
+               }
+       } else {
+               /* Could not set the clock ?!? */
+               __ctl_clear_bit(0, 29);
+               __ctl_clear_bit(14, 21);
+               etr_disable_sync_clock(NULL);
+               in_sync = -EAGAIN;
+               rc = -EAGAIN;
+       }
+       local_irq_enable();
+       smp_call_function(etr_sync_cpu_end,NULL,0,0);
+       preempt_enable();
+       return rc;
+}
+
+/*
+ * Handle the immediate effects of the different events.
+ * The port change event is used for online/offline changes.
+ */
+static struct etr_eacr etr_handle_events(struct etr_eacr eacr)
+{
+       if (test_and_clear_bit(ETR_EVENT_SYNC_CHECK, &etr_events))
+               eacr.es = 0;
+       if (test_and_clear_bit(ETR_EVENT_SWITCH_LOCAL, &etr_events))
+               eacr.es = eacr.sl = 0;
+       if (test_and_clear_bit(ETR_EVENT_PORT_ALERT, &etr_events))
+               etr_port0_uptodate = etr_port1_uptodate = 0;
+
+       if (test_and_clear_bit(ETR_EVENT_PORT0_CHANGE, &etr_events)) {
+               if (eacr.e0)
+                       /*
+                        * Port change of an enabled port. We have to
+                        * assume that this can have caused an stepping
+                        * port switch.
+                        */
+                       etr_tolec = get_clock();
+               eacr.p0 = etr_port0_online;
+               if (!eacr.p0)
+                       eacr.e0 = 0;
+               etr_port0_uptodate = 0;
+       }
+       if (test_and_clear_bit(ETR_EVENT_PORT1_CHANGE, &etr_events)) {
+               if (eacr.e1)
+                       /*
+                        * Port change of an enabled port. We have to
+                        * assume that this can have caused an stepping
+                        * port switch.
+                        */
+                       etr_tolec = get_clock();
+               eacr.p1 = etr_port1_online;
+               if (!eacr.p1)
+                       eacr.e1 = 0;
+               etr_port1_uptodate = 0;
+       }
+       clear_bit(ETR_EVENT_UPDATE, &etr_events);
+       return eacr;
+}
+
+/*
+ * Set up a timer that expires after the etr_tolec + 1.6 seconds if
+ * one of the ports needs an update.
+ */
+static void etr_set_tolec_timeout(unsigned long long now)
+{
+       unsigned long micros;
+
+       if ((!etr_eacr.p0 || etr_port0_uptodate) &&
+           (!etr_eacr.p1 || etr_port1_uptodate))
+               return;
+       micros = (now > etr_tolec) ? ((now - etr_tolec) >> 12) : 0;
+       micros = (micros > 1600000) ? 0 : 1600000 - micros;
+       mod_timer(&etr_timer, jiffies + (micros * HZ) / 1000000 + 1);
+}
+
+/*
+ * Set up a time that expires after 1/2 second.
+ */
+static void etr_set_sync_timeout(void)
+{
+       mod_timer(&etr_timer, jiffies + HZ/2);
+}
+
+/*
+ * Update the aib information for one or both ports.
+ */
+static struct etr_eacr etr_handle_update(struct etr_aib *aib,
+                                        struct etr_eacr eacr)
+{
+       /* With both ports disabled the aib information is useless. */
+       if (!eacr.e0 && !eacr.e1)
+               return eacr;
+
+       /* Update port0 or port1 with aib stored in etr_tasklet_fn. */
+       if (aib->esw.q == 0) {
+               /* Information for port 0 stored. */
+               if (eacr.p0 && !etr_port0_uptodate) {
+                       etr_port0 = *aib;
+                       if (etr_port0_online)
+                               etr_port0_uptodate = 1;
+               }
+       } else {
+               /* Information for port 1 stored. */
+               if (eacr.p1 && !etr_port1_uptodate) {
+                       etr_port1 = *aib;
+                       if (etr_port0_online)
+                               etr_port1_uptodate = 1;
+               }
+       }
+
+       /*
+        * Do not try to get the alternate port aib if the clock
+        * is not in sync yet.
+        */
+       if (!eacr.es)
+               return eacr;
+
+       /*
+        * If steai is available we can get the information about
+        * the other port immediately. If only stetr is available the
+        * data-port bit toggle has to be used.
+        */
+       if (test_bit(ETR_FLAG_STEAI, &etr_flags)) {
+               if (eacr.p0 && !etr_port0_uptodate) {
+                       etr_steai_cv(&etr_port0, ETR_STEAI_PORT_0);
+                       etr_port0_uptodate = 1;
+               }
+               if (eacr.p1 && !etr_port1_uptodate) {
+                       etr_steai_cv(&etr_port1, ETR_STEAI_PORT_1);
+                       etr_port1_uptodate = 1;
+               }
+       } else {
+               /*
+                * One port was updated above, if the other
+                * port is not uptodate toggle dp bit.
+                */
+               if ((eacr.p0 && !etr_port0_uptodate) ||
+                   (eacr.p1 && !etr_port1_uptodate))
+                       eacr.dp ^= 1;
+               else
+                       eacr.dp = 0;
+       }
+       return eacr;
+}
+
+/*
+ * Write new etr control register if it differs from the current one.
+ * Return 1 if etr_tolec has been updated as well.
+ */
+static void etr_update_eacr(struct etr_eacr eacr)
+{
+       int dp_changed;
+
+       if (memcmp(&etr_eacr, &eacr, sizeof(eacr)) == 0)
+               /* No change, return. */
+               return;
+       /*
+        * The disable of an active port of the change of the data port
+        * bit can/will cause a change in the data port.
+        */
+       dp_changed = etr_eacr.e0 > eacr.e0 || etr_eacr.e1 > eacr.e1 ||
+               (etr_eacr.dp ^ eacr.dp) != 0;
+       etr_eacr = eacr;
+       etr_setr(&etr_eacr);
+       if (dp_changed)
+               etr_tolec = get_clock();
+}
+
+/*
+ * ETR tasklet. In this function you'll find the main logic. In
+ * particular this is the only function that calls etr_update_eacr(),
+ * it "controls" the etr control register.
+ */
+static void etr_tasklet_fn(unsigned long dummy)
+{
+       unsigned long long now;
+       struct etr_eacr eacr;
+       struct etr_aib aib;
+       int sync_port;
+
+       /* Create working copy of etr_eacr. */
+       eacr = etr_eacr;
+
+       /* Check for the different events and their immediate effects. */
+       eacr = etr_handle_events(eacr);
+
+       /* Check if ETR is supposed to be active. */
+       eacr.ea = eacr.p0 || eacr.p1;
+       if (!eacr.ea) {
+               /* Both ports offline. Reset everything. */
+               eacr.dp = eacr.es = eacr.sl = 0;
+               on_each_cpu(etr_disable_sync_clock, NULL, 0, 1);
+               del_timer_sync(&etr_timer);
+               etr_update_eacr(eacr);
+               set_bit(ETR_FLAG_EACCES, &etr_flags);
+               return;
+       }
+
+       /* Store aib to get the current ETR status word. */
+       BUG_ON(etr_stetr(&aib) != 0);
+       etr_port0.esw = etr_port1.esw = aib.esw;        /* Copy status word. */
+       now = get_clock();
+
+       /*
+        * Update the port information if the last stepping port change
+        * or data port change is older than 1.6 seconds.
+        */
+       if (now >= etr_tolec + (1600000 << 12))
+               eacr = etr_handle_update(&aib, eacr);
+
+       /*
+        * Select ports to enable. The prefered synchronization mode is PPS.
+        * If a port can be enabled depends on a number of things:
+        * 1) The port needs to be online and uptodate. A port is not
+        *    disabled just because it is not uptodate, but it is only
+        *    enabled if it is uptodate.
+        * 2) The port needs to have the same mode (pps / etr).
+        * 3) The port needs to be usable -> etr_port_valid() == 1
+        * 4) To enable the second port the clock needs to be in sync.
+        * 5) If both ports are useable and are ETR ports, the network id
+        *    has to be the same.
+        * The eacr.sl bit is used to indicate etr mode vs. pps mode.
+        */
+       if (eacr.p0 && aib.esw.psc0 == etr_lpsc_pps_mode) {
+               eacr.sl = 0;
+               eacr.e0 = 1;
+               if (!etr_mode_is_pps(etr_eacr))
+                       eacr.es = 0;
+               if (!eacr.es || !eacr.p1 || aib.esw.psc1 != etr_lpsc_pps_mode)
+                       eacr.e1 = 0;
+               // FIXME: uptodate checks ?
+               else if (etr_port0_uptodate && etr_port1_uptodate)
+                       eacr.e1 = 1;
+               sync_port = (etr_port0_uptodate &&
+                            etr_port_valid(&etr_port0, 0)) ? 0 : -1;
+               clear_bit(ETR_FLAG_EACCES, &etr_flags);
+       } else if (eacr.p1 && aib.esw.psc1 == etr_lpsc_pps_mode) {
+               eacr.sl = 0;
+               eacr.e0 = 0;
+               eacr.e1 = 1;
+               if (!etr_mode_is_pps(etr_eacr))
+                       eacr.es = 0;
+               sync_port = (etr_port1_uptodate &&
+                            etr_port_valid(&etr_port1, 1)) ? 1 : -1;
+               clear_bit(ETR_FLAG_EACCES, &etr_flags);
+       } else if (eacr.p0 && aib.esw.psc0 == etr_lpsc_operational_step) {
+               eacr.sl = 1;
+               eacr.e0 = 1;
+               if (!etr_mode_is_etr(etr_eacr))
+                       eacr.es = 0;
+               if (!eacr.es || !eacr.p1 ||
+                   aib.esw.psc1 != etr_lpsc_operational_alt)
+                       eacr.e1 = 0;
+               else if (etr_port0_uptodate && etr_port1_uptodate &&
+                        etr_compare_network(&etr_port0, &etr_port1))
+                       eacr.e1 = 1;
+               sync_port = (etr_port0_uptodate &&
+                            etr_port_valid(&etr_port0, 0)) ? 0 : -1;
+               clear_bit(ETR_FLAG_EACCES, &etr_flags);
+       } else if (eacr.p1 && aib.esw.psc1 == etr_lpsc_operational_step) {
+               eacr.sl = 1;
+               eacr.e0 = 0;
+               eacr.e1 = 1;
+               if (!etr_mode_is_etr(etr_eacr))
+                       eacr.es = 0;
+               sync_port = (etr_port1_uptodate &&
+                            etr_port_valid(&etr_port1, 1)) ? 1 : -1;
+               clear_bit(ETR_FLAG_EACCES, &etr_flags);
+       } else {
+               /* Both ports not usable. */
+               eacr.es = eacr.sl = 0;
+               sync_port = -1;
+               set_bit(ETR_FLAG_EACCES, &etr_flags);
+       }
+
+       /*
+        * If the clock is in sync just update the eacr and return.
+        * If there is no valid sync port wait for a port update.
+        */
+       if (eacr.es || sync_port < 0) {
+               etr_update_eacr(eacr);
+               etr_set_tolec_timeout(now);
+               return;
+       }
+
+       /*
+        * Prepare control register for clock syncing
+        * (reset data port bit, set sync check control.
+        */
+       eacr.dp = 0;
+       eacr.es = 1;
+
+       /*
+        * Update eacr and try to synchronize the clock. If the update
+        * of eacr caused a stepping port switch (or if we have to
+        * assume that a stepping port switch has occured) or the
+        * clock syncing failed, reset the sync check control bit
+        * and set up a timer to try again after 0.5 seconds
+        */
+       etr_update_eacr(eacr);
+       if (now < etr_tolec + (1600000 << 12) ||
+           etr_sync_clock(&aib, sync_port) != 0) {
+               /* Sync failed. Try again in 1/2 second. */
+               eacr.es = 0;
+               etr_update_eacr(eacr);
+               etr_set_sync_timeout();
+       } else
+               etr_set_tolec_timeout(now);
+}
+
+/*
+ * Sysfs interface functions
+ */
+static struct sysdev_class etr_sysclass = {
+       set_kset_name("etr")
+};
+
+static struct sys_device etr_port0_dev = {
+       .id     = 0,
+       .cls    = &etr_sysclass,
+};
+
+static struct sys_device etr_port1_dev = {
+       .id     = 1,
+       .cls    = &etr_sysclass,
+};
+
+/*
+ * ETR class attributes
+ */
+static ssize_t etr_stepping_port_show(struct sysdev_class *class, char *buf)
+{
+       return sprintf(buf, "%i\n", etr_port0.esw.p);
+}
+
+static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL);
+
+static ssize_t etr_stepping_mode_show(struct sysdev_class *class, char *buf)
+{
+       char *mode_str;
+
+       if (etr_mode_is_pps(etr_eacr))
+               mode_str = "pps";
+       else if (etr_mode_is_etr(etr_eacr))
+               mode_str = "etr";
+       else
+               mode_str = "local";
+       return sprintf(buf, "%s\n", mode_str);
+}
+
+static SYSDEV_CLASS_ATTR(stepping_mode, 0400, etr_stepping_mode_show, NULL);
+
+/*
+ * ETR port attributes
+ */
+static inline struct etr_aib *etr_aib_from_dev(struct sys_device *dev)
+{
+       if (dev == &etr_port0_dev)
+               return etr_port0_online ? &etr_port0 : NULL;
+       else
+               return etr_port1_online ? &etr_port1 : NULL;
+}
+
+static ssize_t etr_online_show(struct sys_device *dev, char *buf)
+{
+       unsigned int online;
+
+       online = (dev == &etr_port0_dev) ? etr_port0_online : etr_port1_online;
+       return sprintf(buf, "%i\n", online);
+}
+
+static ssize_t etr_online_store(struct sys_device *dev,
+                             const char *buf, size_t count)
+{
+       unsigned int value;
+
+       value = simple_strtoul(buf, NULL, 0);
+       if (value != 0 && value != 1)
+               return -EINVAL;
+       if (test_bit(ETR_FLAG_ENOSYS, &etr_flags))
+               return -ENOSYS;
+       if (dev == &etr_port0_dev) {
+               if (etr_port0_online == value)
+                       return count;   /* Nothing to do. */
+               etr_port0_online = value;
+               set_bit(ETR_EVENT_PORT0_CHANGE, &etr_events);
+               tasklet_hi_schedule(&etr_tasklet);
+       } else {
+               if (etr_port1_online == value)
+                       return count;   /* Nothing to do. */
+               etr_port1_online = value;
+               set_bit(ETR_EVENT_PORT1_CHANGE, &etr_events);
+               tasklet_hi_schedule(&etr_tasklet);
+       }
+       return count;
+}
+
+static SYSDEV_ATTR(online, 0600, etr_online_show, etr_online_store);
+
+static ssize_t etr_stepping_control_show(struct sys_device *dev, char *buf)
+{
+       return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ?
+                      etr_eacr.e0 : etr_eacr.e1);
+}
+
+static SYSDEV_ATTR(stepping_control, 0400, etr_stepping_control_show, NULL);
+
+static ssize_t etr_mode_code_show(struct sys_device *dev, char *buf)
+{
+       if (!etr_port0_online && !etr_port1_online)
+               /* Status word is not uptodate if both ports are offline. */
+               return -ENODATA;
+       return sprintf(buf, "%i\n", (dev == &etr_port0_dev) ?
+                      etr_port0.esw.psc0 : etr_port0.esw.psc1);
+}
+
+static SYSDEV_ATTR(state_code, 0400, etr_mode_code_show, NULL);
+
+static ssize_t etr_untuned_show(struct sys_device *dev, char *buf)
+{
+       struct etr_aib *aib = etr_aib_from_dev(dev);
+
+       if (!aib || !aib->slsw.v1)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", aib->edf1.u);
+}
+
+static SYSDEV_ATTR(untuned, 0400, etr_untuned_show, NULL);
+
+static ssize_t etr_network_id_show(struct sys_device *dev, char *buf)
+{
+       struct etr_aib *aib = etr_aib_from_dev(dev);
+
+       if (!aib || !aib->slsw.v1)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", aib->edf1.net_id);
+}
+
+static SYSDEV_ATTR(network, 0400, etr_network_id_show, NULL);
+
+static ssize_t etr_id_show(struct sys_device *dev, char *buf)
+{
+       struct etr_aib *aib = etr_aib_from_dev(dev);
+
+       if (!aib || !aib->slsw.v1)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", aib->edf1.etr_id);
+}
+
+static SYSDEV_ATTR(id, 0400, etr_id_show, NULL);
+
+static ssize_t etr_port_number_show(struct sys_device *dev, char *buf)
+{
+       struct etr_aib *aib = etr_aib_from_dev(dev);
+
+       if (!aib || !aib->slsw.v1)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", aib->edf1.etr_pn);
+}
+
+static SYSDEV_ATTR(port, 0400, etr_port_number_show, NULL);
+
+static ssize_t etr_coupled_show(struct sys_device *dev, char *buf)
+{
+       struct etr_aib *aib = etr_aib_from_dev(dev);
+
+       if (!aib || !aib->slsw.v3)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", aib->edf3.c);
+}
+
+static SYSDEV_ATTR(coupled, 0400, etr_coupled_show, NULL);
+
+static ssize_t etr_local_time_show(struct sys_device *dev, char *buf)
+{
+       struct etr_aib *aib = etr_aib_from_dev(dev);
+
+       if (!aib || !aib->slsw.v3)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", aib->edf3.blto);
+}
+
+static SYSDEV_ATTR(local_time, 0400, etr_local_time_show, NULL);
+
+static ssize_t etr_utc_offset_show(struct sys_device *dev, char *buf)
+{
+       struct etr_aib *aib = etr_aib_from_dev(dev);
+
+       if (!aib || !aib->slsw.v3)
+               return -ENODATA;
+       return sprintf(buf, "%i\n", aib->edf3.buo);
+}
+
+static SYSDEV_ATTR(utc_offset, 0400, etr_utc_offset_show, NULL);
+
+static struct sysdev_attribute *etr_port_attributes[] = {
+       &attr_online,
+       &attr_stepping_control,
+       &attr_state_code,
+       &attr_untuned,
+       &attr_network,
+       &attr_id,
+       &attr_port,
+       &attr_coupled,
+       &attr_local_time,
+       &attr_utc_offset,
+       NULL
+};
+
+static int __init etr_register_port(struct sys_device *dev)
+{
+       struct sysdev_attribute **attr;
+       int rc;
+
+       rc = sysdev_register(dev);
+       if (rc)
+               goto out;
+       for (attr = etr_port_attributes; *attr; attr++) {
+               rc = sysdev_create_file(dev, *attr);
+               if (rc)
+                       goto out_unreg;
+       }
+       return 0;
+out_unreg:
+       for (; attr >= etr_port_attributes; attr--)
+               sysdev_remove_file(dev, *attr);
+       sysdev_unregister(dev);
+out:
+       return rc;
+}
+
+static void __init etr_unregister_port(struct sys_device *dev)
+{
+       struct sysdev_attribute **attr;
+
+       for (attr = etr_port_attributes; *attr; attr++)
+               sysdev_remove_file(dev, *attr);
+       sysdev_unregister(dev);
+}
+
+static int __init etr_init_sysfs(void)
+{
+       int rc;
+
+       rc = sysdev_class_register(&etr_sysclass);
+       if (rc)
+               goto out;
+       rc = sysdev_class_create_file(&etr_sysclass, &attr_stepping_port);
+       if (rc)
+               goto out_unreg_class;
+       rc = sysdev_class_create_file(&etr_sysclass, &attr_stepping_mode);
+       if (rc)
+               goto out_remove_stepping_port;
+       rc = etr_register_port(&etr_port0_dev);
+       if (rc)
+               goto out_remove_stepping_mode;
+       rc = etr_register_port(&etr_port1_dev);
+       if (rc)
+               goto out_remove_port0;
+       return 0;
+
+out_remove_port0:
+       etr_unregister_port(&etr_port0_dev);
+out_remove_stepping_mode:
+       sysdev_class_remove_file(&etr_sysclass, &attr_stepping_mode);
+out_remove_stepping_port:
+       sysdev_class_remove_file(&etr_sysclass, &attr_stepping_port);
+out_unreg_class:
+       sysdev_class_unregister(&etr_sysclass);
+out:
+       return rc;
 }
 
+device_initcall(etr_init_sysfs);
index 3cbb0dcf1f1dc845d744077c95c416796e85ddb0..f0e5a320e2ec4d5e43a94802643bcc722017002e 100644 (file)
@@ -283,7 +283,7 @@ char *task_show_regs(struct task_struct *task, char *buffer)
        return buffer;
 }
 
-DEFINE_SPINLOCK(die_lock);
+static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
@@ -364,8 +364,7 @@ void __kprobes do_single_step(struct pt_regs *regs)
                force_sig(SIGTRAP, current);
 }
 
-asmlinkage void
-default_trap_handler(struct pt_regs * regs, long interruption_code)
+static void default_trap_handler(struct pt_regs * regs, long interruption_code)
 {
         if (regs->psw.mask & PSW_MASK_PSTATE) {
                local_irq_enable();
@@ -376,7 +375,7 @@ default_trap_handler(struct pt_regs * regs, long interruption_code)
 }
 
 #define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \
-asmlinkage void name(struct pt_regs * regs, long interruption_code) \
+static void name(struct pt_regs * regs, long interruption_code) \
 { \
         siginfo_t info; \
         info.si_signo = signr; \
@@ -442,7 +441,7 @@ do_fp_trap(struct pt_regs *regs, void __user *location,
                "floating point exception", regs, &si);
 }
 
-asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
+static void illegal_op(struct pt_regs * regs, long interruption_code)
 {
        siginfo_t info;
         __u8 opcode[6];
@@ -491,8 +490,15 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
 #endif
                } else
                        signal = SIGILL;
-       } else
-               signal = SIGILL;
+       } else {
+               /*
+                * If we get an illegal op in kernel mode, send it through the
+                * kprobes notifier. If kprobes doesn't pick it up, SIGILL
+                */
+               if (notify_die(DIE_BPT, "bpt", regs, interruption_code,
+                              3, SIGTRAP) != NOTIFY_STOP)
+                       signal = SIGILL;
+       }
 
 #ifdef CONFIG_MATHEMU
         if (signal == SIGFPE)
@@ -585,7 +591,7 @@ DO_ERROR_INFO(SIGILL, "specification exception", specification_exception,
              ILL_ILLOPN, get_check_address(regs));
 #endif
 
-asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
+static void data_exception(struct pt_regs * regs, long interruption_code)
 {
        __u16 __user *location;
        int signal = 0;
@@ -675,7 +681,7 @@ asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
        }
 }
 
-asmlinkage void space_switch_exception(struct pt_regs * regs, long int_code)
+static void space_switch_exception(struct pt_regs * regs, long int_code)
 {
         siginfo_t info;
 
index fe0f2e97ba7bb8f063b174a4a1cbe53cda0d350e..a4890739252230df4ebb28cc70a0e79915aa7bd0 100644 (file)
@@ -31,18 +31,19 @@ SECTIONS
 
   _etext = .;                  /* End of text section */
 
-  . = ALIGN(16);               /* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
   RODATA
 
 #ifdef CONFIG_SHARED_KERNEL
   . = ALIGN(1048576);          /* VM shared segments are 1MB aligned */
+#endif
 
+  . = ALIGN(4096);
   _eshared = .;                        /* End of shareable data */
-#endif
+
+  . = ALIGN(16);               /* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
 
   .data : {                    /* Data */
        *(.data)
index 21baaf5496d61b02525a933c8139524710863cfb..9d5b02801b460882cde4928b2a87d2c905f6f0b6 100644 (file)
@@ -25,7 +25,7 @@
 #include <asm/irq_regs.h>
 
 static ext_int_info_t ext_int_info_timer;
-DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
+static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 /*
@@ -524,16 +524,15 @@ EXPORT_SYMBOL(del_virt_timer);
 void init_cpu_vtimer(void)
 {
        struct vtimer_queue *vt_list;
-       unsigned long cr0;
 
        /* kick the virtual timer */
        S390_lowcore.exit_timer = VTIMER_MAX_SLICE;
        S390_lowcore.last_update_timer = VTIMER_MAX_SLICE;
        asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer));
        asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
-       __ctl_store(cr0, 0, 0);
-       cr0 |= 0x400;
-       __ctl_load(cr0, 0, 0);
+
+       /* enable cpu timer interrupts */
+       __ctl_set_bit(0,10);
 
        vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
        INIT_LIST_HEAD(&vt_list->list);
@@ -572,6 +571,7 @@ void __init vtime_init(void)
        if (register_idle_notifier(&vtimer_idle_nb))
                panic("Couldn't register idle notifier");
 
+       /* Enable cpu timer interrupts on the boot cpu. */
        init_cpu_vtimer();
 }
 
index b5f94cf3bde8d190d09c66fec8bfcc289d5f3292..7a44fed21b35cb39f1beb1991991ab48bcb3d0a7 100644 (file)
@@ -4,7 +4,7 @@
 
 EXTRA_AFLAGS := -traditional
 
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o qrnnd.o
 lib-$(CONFIG_32BIT) += div64.o
 lib-$(CONFIG_64BIT) += uaccess_mvcos.o
 lib-$(CONFIG_SMP) += spinlock.o
index 027c4742a0017a2cdef12b51a4dd282709dc59b9..02854449b74ba64dea7230b606f72b63c3890218 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  arch/s390/kernel/delay.c
+ *  arch/s390/lib/delay.c
  *    Precise Delay Loops for S390
  *
  *  S390 version
 
 #include <linux/sched.h>
 #include <linux/delay.h>
-
-#ifdef CONFIG_SMP
-#include <asm/smp.h>
-#endif
+#include <linux/timex.h>
+#include <linux/irqflags.h>
 
 void __delay(unsigned long loops)
 {
@@ -31,17 +29,39 @@ void __delay(unsigned long loops)
 }
 
 /*
- * Waits for 'usecs' microseconds using the tod clock, giving up the time slice
- * of the virtual PU inbetween to avoid congestion.
+ * Waits for 'usecs' microseconds using the TOD clock comparator.
  */
 void __udelay(unsigned long usecs)
 {
-       uint64_t start_cc;
+       u64 end, time, jiffy_timer = 0;
+       unsigned long flags, cr0, mask, dummy;
+
+       local_irq_save(flags);
+       if (raw_irqs_disabled_flags(flags)) {
+               jiffy_timer = S390_lowcore.jiffy_timer;
+               S390_lowcore.jiffy_timer = -1ULL - (4096 << 12);
+               __ctl_store(cr0, 0, 0);
+               dummy = (cr0 & 0xffff00e0) | 0x00000800;
+               __ctl_load(dummy , 0, 0);
+               mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
+       } else
+               mask = psw_kernel_bits | PSW_MASK_WAIT |
+                       PSW_MASK_EXT | PSW_MASK_IO;
+
+       end = get_clock() + ((u64) usecs << 12);
+       do {
+               time = end < S390_lowcore.jiffy_timer ?
+                       end : S390_lowcore.jiffy_timer;
+               set_clock_comparator(time);
+               trace_hardirqs_on();
+               __load_psw_mask(mask);
+               local_irq_disable();
+       } while (get_clock() < end);
 
-        if (usecs == 0)
-                return;
-       start_cc = get_clock();
-        do {
-               cpu_relax();
-       } while (((get_clock() - start_cc)/4096) < usecs);
+       if (raw_irqs_disabled_flags(flags)) {
+               __ctl_load(cr0, 0, 0);
+               S390_lowcore.jiffy_timer = jiffy_timer;
+       }
+       set_clock_comparator(S390_lowcore.jiffy_timer);
+       local_irq_restore(flags);
 }
diff --git a/arch/s390/lib/qrnnd.S b/arch/s390/lib/qrnnd.S
new file mode 100644 (file)
index 0000000..eb1df63
--- /dev/null
@@ -0,0 +1,77 @@
+# S/390 __udiv_qrnnd
+
+# r2 : &__r
+# r3 : upper half of 64 bit word n
+# r4 : lower half of 64 bit word n
+# r5 : divisor d
+# the reminder r of the division is to be stored to &__r and
+# the quotient q is to be returned
+
+       .text
+       .globl __udiv_qrnnd
+__udiv_qrnnd:
+       st    %r2,24(%r15)        # store pointer to reminder for later
+       lr    %r0,%r3             # reload n
+       lr    %r1,%r4
+       ltr   %r2,%r5             # reload and test divisor
+       jp    5f
+       # divisor >= 0x80000000
+       srdl  %r0,2               # n/4
+       srl   %r2,1               # d/2
+       slr   %r1,%r2             # special case if last bit of d is set
+       brc   3,0f                #  (n/4) div (n/2) can overflow by 1
+       ahi   %r0,-1              #  trick: subtract n/2, then divide
+0:     dr    %r0,%r2             # signed division
+       ahi   %r1,1               #  trick part 2: add 1 to the quotient
+       # now (n >> 2) = (d >> 1) * %r1 + %r0
+       lhi   %r3,1
+       nr    %r3,%r1             # test last bit of q
+       jz    1f
+       alr   %r0,%r2             # add (d>>1) to r
+1:     srl   %r1,1               # q >>= 1
+       # now (n >> 2) = (d&-2) * %r1 + %r0
+       lhi   %r3,1
+       nr    %r3,%r5             # test last bit of d
+       jz    2f
+       slr   %r0,%r1             # r -= q
+       brc   3,2f                # borrow ?
+       alr   %r0,%r5             # r += d
+       ahi   %r1,-1
+2:     # now (n >> 2) = d * %r1 + %r0
+       alr   %r1,%r1             # q <<= 1
+       alr   %r0,%r0             # r <<= 1
+       brc   12,3f               # overflow on r ?
+       slr   %r0,%r5             # r -= d
+       ahi   %r1,1               # q += 1
+3:     lhi   %r3,2
+       nr    %r3,%r4             # test next to last bit of n
+       jz    4f
+       ahi   %r0,1               # r += 1
+4:     clr   %r0,%r5             # r >= d ?
+       jl    6f
+       slr   %r0,%r5             # r -= d
+       ahi   %r1,1               # q += 1
+       # now (n >> 1) = d * %r1 + %r0
+       j     6f
+5:     # divisor < 0x80000000
+       srdl  %r0,1
+       dr    %r0,%r2             # signed division
+       # now (n >> 1) = d * %r1 + %r0
+6:     alr   %r1,%r1             # q <<= 1
+       alr   %r0,%r0             # r <<= 1
+       brc   12,7f               # overflow on r ?
+       slr   %r0,%r5             # r -= d
+       ahi   %r1,1               # q += 1
+7:     lhi   %r3,1
+       nr    %r3,%r4             # isolate last bit of n
+       alr   %r0,%r3             # r += (n & 1)
+       clr   %r0,%r5             # r >= d ?
+       jl    8f
+       slr   %r0,%r5             # r -= d
+       ahi   %r1,1               # q += 1
+8:     # now n = d * %r1 + %r0
+       l     %r2,24(%r15)
+       st    %r0,0(%r2)
+       lr    %r2,%r1
+       br    %r14
+       .end    __udiv_qrnnd
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
new file mode 100644 (file)
index 0000000..126011d
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  arch/s390/uaccess.h
+ *
+ *    Copyright IBM Corp. 2007
+ *
+ */
+
+#ifndef __ARCH_S390_LIB_UACCESS_H
+#define __ARCH_S390_LIB_UACCESS_H
+
+extern size_t copy_from_user_std(size_t, const void __user *, void *);
+extern size_t copy_to_user_std(size_t, void __user *, const void *);
+extern size_t strnlen_user_std(size_t, const char __user *);
+extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
+extern int futex_atomic_cmpxchg_std(int __user *, int, int);
+extern int futex_atomic_op_std(int, int __user *, int, int *);
+
+extern size_t copy_from_user_pt(size_t, const void __user *, void *);
+extern size_t copy_to_user_pt(size_t, void __user *, const void *);
+extern int futex_atomic_op_pt(int, int __user *, int, int *);
+extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
+
+#endif /* __ARCH_S390_LIB_UACCESS_H */
index f9a23d57eb79fa63713a7ac87e85f1991c30280f..6d8772339d76182db7a7d0b03cf03067194b3fca 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/futex.h>
+#include "uaccess.h"
 
 #ifndef __s390x__
 #define AHI    "ahi"
 #define SLR    "slgr"
 #endif
 
-extern size_t copy_from_user_std(size_t, const void __user *, void *);
-extern size_t copy_to_user_std(size_t, void __user *, const void *);
-
-size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
+static size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
 {
        register unsigned long reg0 asm("0") = 0x81UL;
        unsigned long tmp1, tmp2;
@@ -69,14 +67,14 @@ size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x)
        return size;
 }
 
-size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x)
+static size_t copy_from_user_mvcos_check(size_t size, const void __user *ptr, void *x)
 {
        if (size <= 256)
                return copy_from_user_std(size, ptr, x);
        return copy_from_user_mvcos(size, ptr, x);
 }
 
-size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
+static size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
 {
        register unsigned long reg0 asm("0") = 0x810000UL;
        unsigned long tmp1, tmp2;
@@ -105,14 +103,16 @@ size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x)
        return size;
 }
 
-size_t copy_to_user_mvcos_check(size_t size, void __user *ptr, const void *x)
+static size_t copy_to_user_mvcos_check(size_t size, void __user *ptr,
+                                      const void *x)
 {
        if (size <= 256)
                return copy_to_user_std(size, ptr, x);
        return copy_to_user_mvcos(size, ptr, x);
 }
 
-size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from)
+static size_t copy_in_user_mvcos(size_t size, void __user *to,
+                                const void __user *from)
 {
        register unsigned long reg0 asm("0") = 0x810081UL;
        unsigned long tmp1, tmp2;
@@ -134,7 +134,7 @@ size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from)
        return size;
 }
 
-size_t clear_user_mvcos(size_t size, void __user *to)
+static size_t clear_user_mvcos(size_t size, void __user *to)
 {
        register unsigned long reg0 asm("0") = 0x810000UL;
        unsigned long tmp1, tmp2;
@@ -162,10 +162,43 @@ size_t clear_user_mvcos(size_t size, void __user *to)
        return size;
 }
 
-extern size_t strnlen_user_std(size_t, const char __user *);
-extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_op(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg(int __user *, int, int);
+static size_t strnlen_user_mvcos(size_t count, const char __user *src)
+{
+       char buf[256];
+       int rc;
+       size_t done, len, len_str;
+
+       done = 0;
+       do {
+               len = min(count - done, (size_t) 256);
+               rc = uaccess.copy_from_user(len, src + done, buf);
+               if (unlikely(rc == len))
+                       return 0;
+               len -= rc;
+               len_str = strnlen(buf, len);
+               done += len_str;
+       } while ((len_str == len) && (done < count));
+       return done + 1;
+}
+
+static size_t strncpy_from_user_mvcos(size_t count, const char __user *src,
+                                     char *dst)
+{
+       int rc;
+       size_t done, len, len_str;
+
+       done = 0;
+       do {
+               len = min(count - done, (size_t) 4096);
+               rc = uaccess.copy_from_user(len, src + done, dst);
+               if (unlikely(rc == len))
+                       return -EFAULT;
+               len -= rc;
+               len_str = strnlen(dst, len);
+               done += len_str;
+       } while ((len_str == len) && (done < count));
+       return done;
+}
 
 struct uaccess_ops uaccess_mvcos = {
        .copy_from_user = copy_from_user_mvcos_check,
@@ -176,6 +209,21 @@ struct uaccess_ops uaccess_mvcos = {
        .clear_user = clear_user_mvcos,
        .strnlen_user = strnlen_user_std,
        .strncpy_from_user = strncpy_from_user_std,
-       .futex_atomic_op = futex_atomic_op,
-       .futex_atomic_cmpxchg = futex_atomic_cmpxchg,
+       .futex_atomic_op = futex_atomic_op_std,
+       .futex_atomic_cmpxchg = futex_atomic_cmpxchg_std,
+};
+
+#ifdef CONFIG_S390_SWITCH_AMODE
+struct uaccess_ops uaccess_mvcos_switch = {
+       .copy_from_user = copy_from_user_mvcos,
+       .copy_from_user_small = copy_from_user_mvcos,
+       .copy_to_user = copy_to_user_mvcos,
+       .copy_to_user_small = copy_to_user_mvcos,
+       .copy_in_user = copy_in_user_mvcos,
+       .clear_user = clear_user_mvcos,
+       .strnlen_user = strnlen_user_mvcos,
+       .strncpy_from_user = strncpy_from_user_mvcos,
+       .futex_atomic_op = futex_atomic_op_pt,
+       .futex_atomic_cmpxchg = futex_atomic_cmpxchg_pt,
 };
+#endif
index 49c3e46b406573011d591bbcbd36e6825deb0578..63181671e3e3bfc4ed951dc907ffef1b99d635ae 100644 (file)
@@ -1,7 +1,8 @@
 /*
  *  arch/s390/lib/uaccess_pt.c
  *
- *  User access functions based on page table walks.
+ *  User access functions based on page table walks for enhanced
+ *  system layout without hardware support.
  *
  *    Copyright IBM Corp. 2006
  *    Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com)
 #include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/futex.h>
+#include "uaccess.h"
 
-static inline int __handle_fault(struct mm_struct *mm, unsigned long address,
-                                int write_access)
+static int __handle_fault(struct mm_struct *mm, unsigned long address,
+                         int write_access)
 {
        struct vm_area_struct *vma;
        int ret = -EFAULT;
@@ -79,8 +81,8 @@ out_sigbus:
        return ret;
 }
 
-static inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
-                                   size_t n, int write_user)
+static size_t __user_copy_pt(unsigned long uaddr, void *kptr,
+                            size_t n, int write_user)
 {
        struct mm_struct *mm = current->mm;
        unsigned long offset, pfn, done, size;
@@ -133,6 +135,49 @@ fault:
        goto retry;
 }
 
+/*
+ * Do DAT for user address by page table walk, return kernel address.
+ * This function needs to be called with current->mm->page_table_lock held.
+ */
+static unsigned long __dat_user_addr(unsigned long uaddr)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long pfn, ret;
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
+       int rc;
+
+       ret = 0;
+retry:
+       pgd = pgd_offset(mm, uaddr);
+       if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+               goto fault;
+
+       pmd = pmd_offset(pgd, uaddr);
+       if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+               goto fault;
+
+       pte = pte_offset_map(pmd, uaddr);
+       if (!pte || !pte_present(*pte))
+               goto fault;
+
+       pfn = pte_pfn(*pte);
+       if (!pfn_valid(pfn))
+               goto out;
+
+       ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
+out:
+       return ret;
+fault:
+       spin_unlock(&mm->page_table_lock);
+       rc = __handle_fault(mm, uaddr, 0);
+       spin_lock(&mm->page_table_lock);
+       if (rc)
+               goto out;
+       goto retry;
+}
+
 size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
 {
        size_t rc;
@@ -155,3 +200,277 @@ size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
        }
        return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
 }
+
+static size_t clear_user_pt(size_t n, void __user *to)
+{
+       long done, size, ret;
+
+       if (segment_eq(get_fs(), KERNEL_DS)) {
+               memset((void __kernel __force *) to, 0, n);
+               return 0;
+       }
+       done = 0;
+       do {
+               if (n - done > PAGE_SIZE)
+                       size = PAGE_SIZE;
+               else
+                       size = n - done;
+               ret = __user_copy_pt((unsigned long) to + done,
+                                     &empty_zero_page, size, 1);
+               done += size;
+               if (ret)
+                       return ret + n - done;
+       } while (done < n);
+       return 0;
+}
+
+static size_t strnlen_user_pt(size_t count, const char __user *src)
+{
+       char *addr;
+       unsigned long uaddr = (unsigned long) src;
+       struct mm_struct *mm = current->mm;
+       unsigned long offset, pfn, done, len;
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
+       size_t len_str;
+
+       if (segment_eq(get_fs(), KERNEL_DS))
+               return strnlen((const char __kernel __force *) src, count) + 1;
+       done = 0;
+retry:
+       spin_lock(&mm->page_table_lock);
+       do {
+               pgd = pgd_offset(mm, uaddr);
+               if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+                       goto fault;
+
+               pmd = pmd_offset(pgd, uaddr);
+               if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+                       goto fault;
+
+               pte = pte_offset_map(pmd, uaddr);
+               if (!pte || !pte_present(*pte))
+                       goto fault;
+
+               pfn = pte_pfn(*pte);
+               if (!pfn_valid(pfn)) {
+                       done = -1;
+                       goto out;
+               }
+
+               offset = uaddr & (PAGE_SIZE-1);
+               addr = (char *)(pfn << PAGE_SHIFT) + offset;
+               len = min(count - done, PAGE_SIZE - offset);
+               len_str = strnlen(addr, len);
+               done += len_str;
+               uaddr += len_str;
+       } while ((len_str == len) && (done < count));
+out:
+       spin_unlock(&mm->page_table_lock);
+       return done + 1;
+fault:
+       spin_unlock(&mm->page_table_lock);
+       if (__handle_fault(mm, uaddr, 0)) {
+               return 0;
+       }
+       goto retry;
+}
+
+static size_t strncpy_from_user_pt(size_t count, const char __user *src,
+                                  char *dst)
+{
+       size_t n = strnlen_user_pt(count, src);
+
+       if (!n)
+               return -EFAULT;
+       if (n > count)
+               n = count;
+       if (segment_eq(get_fs(), KERNEL_DS)) {
+               memcpy(dst, (const char __kernel __force *) src, n);
+               if (dst[n-1] == '\0')
+                       return n-1;
+               else
+                       return n;
+       }
+       if (__user_copy_pt((unsigned long) src, dst, n, 0))
+               return -EFAULT;
+       if (dst[n-1] == '\0')
+               return n-1;
+       else
+               return n;
+}
+
+static size_t copy_in_user_pt(size_t n, void __user *to,
+                             const void __user *from)
+{
+       struct mm_struct *mm = current->mm;
+       unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to,
+                     uaddr, done, size;
+       unsigned long uaddr_from = (unsigned long) from;
+       unsigned long uaddr_to = (unsigned long) to;
+       pgd_t *pgd_from, *pgd_to;
+       pmd_t *pmd_from, *pmd_to;
+       pte_t *pte_from, *pte_to;
+       int write_user;
+
+       done = 0;
+retry:
+       spin_lock(&mm->page_table_lock);
+       do {
+               pgd_from = pgd_offset(mm, uaddr_from);
+               if (pgd_none(*pgd_from) || unlikely(pgd_bad(*pgd_from))) {
+                       uaddr = uaddr_from;
+                       write_user = 0;
+                       goto fault;
+               }
+               pgd_to = pgd_offset(mm, uaddr_to);
+               if (pgd_none(*pgd_to) || unlikely(pgd_bad(*pgd_to))) {
+                       uaddr = uaddr_to;
+                       write_user = 1;
+                       goto fault;
+               }
+
+               pmd_from = pmd_offset(pgd_from, uaddr_from);
+               if (pmd_none(*pmd_from) || unlikely(pmd_bad(*pmd_from))) {
+                       uaddr = uaddr_from;
+                       write_user = 0;
+                       goto fault;
+               }
+               pmd_to = pmd_offset(pgd_to, uaddr_to);
+               if (pmd_none(*pmd_to) || unlikely(pmd_bad(*pmd_to))) {
+                       uaddr = uaddr_to;
+                       write_user = 1;
+                       goto fault;
+               }
+
+               pte_from = pte_offset_map(pmd_from, uaddr_from);
+               if (!pte_from || !pte_present(*pte_from)) {
+                       uaddr = uaddr_from;
+                       write_user = 0;
+                       goto fault;
+               }
+               pte_to = pte_offset_map(pmd_to, uaddr_to);
+               if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) {
+                       uaddr = uaddr_to;
+                       write_user = 1;
+                       goto fault;
+               }
+
+               pfn_from = pte_pfn(*pte_from);
+               if (!pfn_valid(pfn_from))
+                       goto out;
+               pfn_to = pte_pfn(*pte_to);
+               if (!pfn_valid(pfn_to))
+                       goto out;
+
+               offset_from = uaddr_from & (PAGE_SIZE-1);
+               offset_to = uaddr_from & (PAGE_SIZE-1);
+               offset_max = max(offset_from, offset_to);
+               size = min(n - done, PAGE_SIZE - offset_max);
+
+               memcpy((void *)(pfn_to << PAGE_SHIFT) + offset_to,
+                      (void *)(pfn_from << PAGE_SHIFT) + offset_from, size);
+               done += size;
+               uaddr_from += size;
+               uaddr_to += size;
+       } while (done < n);
+out:
+       spin_unlock(&mm->page_table_lock);
+       return n - done;
+fault:
+       spin_unlock(&mm->page_table_lock);
+       if (__handle_fault(mm, uaddr, write_user))
+               return n - done;
+       goto retry;
+}
+
+#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg)     \
+       asm volatile("0: l   %1,0(%6)\n"                                \
+                    "1: " insn                                         \
+                    "2: cs  %1,%2,0(%6)\n"                             \
+                    "3: jl  1b\n"                                      \
+                    "   lhi %0,0\n"                                    \
+                    "4:\n"                                             \
+                    EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b)    \
+                    : "=d" (ret), "=&d" (oldval), "=&d" (newval),      \
+                      "=m" (*uaddr)                                    \
+                    : "0" (-EFAULT), "d" (oparg), "a" (uaddr),         \
+                      "m" (*uaddr) : "cc" );
+
+int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+{
+       int oldval = 0, newval, ret;
+
+       spin_lock(&current->mm->page_table_lock);
+       uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+       if (!uaddr) {
+               spin_unlock(&current->mm->page_table_lock);
+               return -EFAULT;
+       }
+       get_page(virt_to_page(uaddr));
+       spin_unlock(&current->mm->page_table_lock);
+       switch (op) {
+       case FUTEX_OP_SET:
+               __futex_atomic_op("lr %2,%5\n",
+                                 ret, oldval, newval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ADD:
+               __futex_atomic_op("lr %2,%1\nar %2,%5\n",
+                                 ret, oldval, newval, uaddr, oparg);
+               break;
+       case FUTEX_OP_OR:
+               __futex_atomic_op("lr %2,%1\nor %2,%5\n",
+                                 ret, oldval, newval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ANDN:
+               __futex_atomic_op("lr %2,%1\nnr %2,%5\n",
+                                 ret, oldval, newval, uaddr, oparg);
+               break;
+       case FUTEX_OP_XOR:
+               __futex_atomic_op("lr %2,%1\nxr %2,%5\n",
+                                 ret, oldval, newval, uaddr, oparg);
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+       put_page(virt_to_page(uaddr));
+       *old = oldval;
+       return ret;
+}
+
+int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+{
+       int ret;
+
+       spin_lock(&current->mm->page_table_lock);
+       uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
+       if (!uaddr) {
+               spin_unlock(&current->mm->page_table_lock);
+               return -EFAULT;
+       }
+       get_page(virt_to_page(uaddr));
+       spin_unlock(&current->mm->page_table_lock);
+       asm volatile("   cs   %1,%4,0(%5)\n"
+                    "0: lr   %0,%1\n"
+                    "1:\n"
+                    EX_TABLE(0b,1b)
+                    : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
+                    : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
+                    : "cc", "memory" );
+       put_page(virt_to_page(uaddr));
+       return ret;
+}
+
+struct uaccess_ops uaccess_pt = {
+       .copy_from_user         = copy_from_user_pt,
+       .copy_from_user_small   = copy_from_user_pt,
+       .copy_to_user           = copy_to_user_pt,
+       .copy_to_user_small     = copy_to_user_pt,
+       .copy_in_user           = copy_in_user_pt,
+       .clear_user             = clear_user_pt,
+       .strnlen_user           = strnlen_user_pt,
+       .strncpy_from_user      = strncpy_from_user_pt,
+       .futex_atomic_op        = futex_atomic_op_pt,
+       .futex_atomic_cmpxchg   = futex_atomic_cmpxchg_pt,
+};
index 56a0214e9928c371c6cce379e599aaf0f61ef8cd..28c4500a58d0abb6556a0105f41ff9a0763e444b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/mm.h>
 #include <linux/uaccess.h>
 #include <asm/futex.h>
+#include "uaccess.h"
 
 #ifndef __s390x__
 #define AHI    "ahi"
@@ -28,9 +29,6 @@
 #define SLR    "slgr"
 #endif
 
-extern size_t copy_from_user_pt(size_t n, const void __user *from, void *to);
-extern size_t copy_to_user_pt(size_t n, void __user *to, const void *from);
-
 size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
 {
        unsigned long tmp1, tmp2;
@@ -72,7 +70,8 @@ size_t copy_from_user_std(size_t size, const void __user *ptr, void *x)
        return size;
 }
 
-size_t copy_from_user_std_check(size_t size, const void __user *ptr, void *x)
+static size_t copy_from_user_std_check(size_t size, const void __user *ptr,
+                                      void *x)
 {
        if (size <= 1024)
                return copy_from_user_std(size, ptr, x);
@@ -110,14 +109,16 @@ size_t copy_to_user_std(size_t size, void __user *ptr, const void *x)
        return size;
 }
 
-size_t copy_to_user_std_check(size_t size, void __user *ptr, const void *x)
+static size_t copy_to_user_std_check(size_t size, void __user *ptr,
+                                    const void *x)
 {
        if (size <= 1024)
                return copy_to_user_std(size, ptr, x);
        return copy_to_user_pt(size, ptr, x);
 }
 
-size_t copy_in_user_std(size_t size, void __user *to, const void __user *from)
+static size_t copy_in_user_std(size_t size, void __user *to,
+                              const void __user *from)
 {
        unsigned long tmp1;
 
@@ -148,7 +149,7 @@ size_t copy_in_user_std(size_t size, void __user *to, const void __user *from)
        return size;
 }
 
-size_t clear_user_std(size_t size, void __user *to)
+static size_t clear_user_std(size_t size, void __user *to)
 {
        unsigned long tmp1, tmp2;
 
@@ -254,7 +255,7 @@ size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst)
                : "0" (-EFAULT), "d" (oparg), "a" (uaddr),              \
                  "m" (*uaddr) : "cc");
 
-int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
 {
        int oldval = 0, newval, ret;
 
@@ -286,7 +287,7 @@ int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old)
        return ret;
 }
 
-int futex_atomic_cmpxchg(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
 {
        int ret;
 
@@ -311,6 +312,6 @@ struct uaccess_ops uaccess_std = {
        .clear_user = clear_user_std,
        .strnlen_user = strnlen_user_std,
        .strncpy_from_user = strncpy_from_user_std,
-       .futex_atomic_op = futex_atomic_op,
-       .futex_atomic_cmpxchg = futex_atomic_cmpxchg,
+       .futex_atomic_op = futex_atomic_op_std,
+       .futex_atomic_cmpxchg = futex_atomic_cmpxchg_std,
 };
index c10df144f2ab44fe298b60ab1192ad08d8edd115..73b3e72efc46a460cc62a31c59400dbae232dedf 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the FPU instruction emulation.
 #
 
-obj-$(CONFIG_MATHEMU) := math.o qrnnd.o
+obj-$(CONFIG_MATHEMU) := math.o
 
 EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w
 EXTRA_AFLAGS := -traditional
index 6b9aec5a2c18dae0283d61904b37b6018691e36c..3ee78ccb617da4783430e79aa67efefec0ceda8c 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
 
-#include "sfp-util.h"
+#include <asm/sfp-util.h>
 #include <math-emu/soft-fp.h>
 #include <math-emu/single.h>
 #include <math-emu/double.h>
diff --git a/arch/s390/math-emu/qrnnd.S b/arch/s390/math-emu/qrnnd.S
deleted file mode 100644 (file)
index b01c2b6..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-# S/390 __udiv_qrnnd
-
-# r2 : &__r
-# r3 : upper half of 64 bit word n
-# r4 : lower half of 64 bit word n
-# r5 : divisor d
-# the reminder r of the division is to be stored to &__r and
-# the quotient q is to be returned
-
-        .text
-        .globl __udiv_qrnnd
-__udiv_qrnnd:
-        st    %r2,24(%r15)        # store pointer to reminder for later
-        lr    %r0,%r3             # reload n
-       lr    %r1,%r4
-       ltr   %r2,%r5             # reload and test divisor
-        jp    5f
-        # divisor >= 0x80000000
-       srdl  %r0,2               # n/4
-        srl   %r2,1               # d/2
-        slr   %r1,%r2             # special case if last bit of d is set
-        brc   3,0f                #  (n/4) div (n/2) can overflow by 1
-        ahi   %r0,-1              #  trick: subtract n/2, then divide
-0:      dr    %r0,%r2             # signed division
-        ahi   %r1,1               #  trick part 2: add 1 to the quotient
-        # now (n >> 2) = (d >> 1) * %r1 + %r0
-       lhi   %r3,1
-        nr    %r3,%r1             # test last bit of q
-        jz    1f
-        alr   %r0,%r2             # add (d>>1) to r
-1:      srl   %r1,1               # q >>= 1
-        # now (n >> 2) = (d&-2) * %r1 + %r0
-        lhi   %r3,1
-        nr    %r3,%r5             # test last bit of d
-        jz    2f
-        slr   %r0,%r1             # r -= q
-       brc   3,2f                # borrow ?
-       alr   %r0,%r5             # r += d
-       ahi   %r1,-1
-2:      # now (n >> 2) = d * %r1 + %r0
-        alr   %r1,%r1             # q <<= 1
-        alr   %r0,%r0             # r <<= 1
-        brc   12,3f               # overflow on r ?
-        slr   %r0,%r5             # r -= d
-        ahi   %r1,1               # q += 1
-3:      lhi   %r3,2
-        nr    %r3,%r4             # test next to last bit of n
-        jz    4f
-        ahi   %r0,1               # r += 1
-4:      clr   %r0,%r5             # r >= d ?
-        jl    6f
-        slr   %r0,%r5             # r -= d
-        ahi   %r1,1               # q += 1
-        # now (n >> 1) = d * %r1 + %r0
-        j     6f
-5:      # divisor < 0x80000000
-       srdl  %r0,1
-        dr    %r0,%r2             # signed division
-        # now (n >> 1) = d * %r1 + %r0
-6:      alr   %r1,%r1             # q <<= 1
-        alr   %r0,%r0             # r <<= 1
-        brc   12,7f               # overflow on r ?
-        slr   %r0,%r5             # r -= d
-        ahi   %r1,1               # q += 1
-7:      lhi   %r3,1
-        nr    %r3,%r4             # isolate last bit of n
-        alr   %r0,%r3             # r += (n & 1)
-        clr   %r0,%r5             # r >= d ?
-        jl    8f
-        slr   %r0,%r5             # r -= d
-        ahi   %r1,1               # q += 1
-8:      # now n = d * %r1 + %r0
-       l     %r2,24(%r15)
-        st    %r0,0(%r2)
-        lr    %r2,%r1
-        br    %r14
-       .end    __udiv_qrnnd
index 607f50ead1fd4d0c7077487bf39ca3392121effd..f93a056869bc5aa7d38f1a88810acf019029eacf 100644 (file)
@@ -245,7 +245,7 @@ cmm_set_timeout(long nr, long seconds)
        cmm_set_timer();
 }
 
-static inline int
+static int
 cmm_skip_blanks(char *cp, char **endp)
 {
        char *str;
@@ -414,7 +414,7 @@ cmm_smsg_target(char *from, char *msg)
 }
 #endif
 
-struct ctl_table_header *cmm_sysctl_header;
+static struct ctl_table_header *cmm_sysctl_header;
 
 static int
 cmm_init (void)
index 775bf19e742be2051a74b74fe0c3b06367d8769b..394980b05e6fd91aaea02bacca57f81062690ad4 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/bootmem.h>
 #include <linux/ctype.h>
+#include <linux/ioport.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/ebcdic.h>
@@ -70,6 +71,7 @@ struct qin64 {
 struct dcss_segment {
        struct list_head list;
        char dcss_name[8];
+       char res_name[15];
        unsigned long start_addr;
        unsigned long end;
        atomic_t ref_count;
@@ -77,6 +79,7 @@ struct dcss_segment {
        unsigned int vm_segtype;
        struct qrange range[6];
        int segcnt;
+       struct resource *res;
 };
 
 static DEFINE_MUTEX(dcss_lock);
@@ -88,7 +91,7 @@ static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC",
  * Create the 8 bytes, ebcdic VM segment name from
  * an ascii name.
  */
-static void inline
+static void
 dcss_mkname(char *name, char *dcss_name)
 {
        int i;
@@ -303,6 +306,29 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
                goto out_free;
        }
 
+       seg->res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+       if (seg->res == NULL) {
+               rc = -ENOMEM;
+               goto out_shared;
+       }
+       seg->res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
+       seg->res->start = seg->start_addr;
+       seg->res->end = seg->end;
+       memcpy(&seg->res_name, seg->dcss_name, 8);
+       EBCASC(seg->res_name, 8);
+       seg->res_name[8] = '\0';
+       strncat(seg->res_name, " (DCSS)", 7);
+       seg->res->name = seg->res_name;
+       rc = seg->vm_segtype;
+       if (rc == SEG_TYPE_SC ||
+           ((rc == SEG_TYPE_SR || rc == SEG_TYPE_ER) && !do_nonshared))
+               seg->res->flags |= IORESOURCE_READONLY;
+       if (request_resource(&iomem_resource, seg->res)) {
+               rc = -EBUSY;
+               kfree(seg->res);
+               goto out_shared;
+       }
+
        if (do_nonshared)
                dcss_command = DCSS_LOADNSR;
        else
@@ -316,12 +342,11 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
                rc = dcss_diag_translate_rc (seg->end);
                dcss_diag(DCSS_PURGESEG, seg->dcss_name,
                                &seg->start_addr, &seg->end);
-               goto out_shared;
+               goto out_resource;
        }
        seg->do_nonshared = do_nonshared;
        atomic_set(&seg->ref_count, 1);
        list_add(&seg->list, &dcss_list);
-       rc = seg->vm_segtype;
        *addr = seg->start_addr;
        *end  = seg->end;
        if (do_nonshared)
@@ -329,12 +354,16 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
                                "type %s in non-shared mode\n", name,
                                (void*)seg->start_addr, (void*)seg->end,
                                segtype_string[seg->vm_segtype]);
-       else
+       else {
                PRINT_INFO ("segment_load: loaded segment %s range %p .. %p "
                                "type %s in shared mode\n", name,
                                (void*)seg->start_addr, (void*)seg->end,
                                segtype_string[seg->vm_segtype]);
+       }
        goto out;
+ out_resource:
+       release_resource(seg->res);
+       kfree(seg->res);
  out_shared:
        remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
  out_free:
@@ -401,6 +430,7 @@ segment_load (char *name, int do_nonshared, unsigned long *addr,
  * -ENOENT  : no such segment (segment gone!)
  * -EAGAIN  : segment is in use by other exploiters, try later
  * -EINVAL  : no segment with the given name is currently loaded - name invalid
+ * -EBUSY   : segment can temporarily not be used (overlaps with dcss)
  * 0       : operation succeeded
  */
 int
@@ -428,12 +458,24 @@ segment_modify_shared (char *name, int do_nonshared)
                rc = -EAGAIN;
                goto out_unlock;
        }
-       dcss_diag(DCSS_PURGESEG, seg->dcss_name,
-                 &dummy, &dummy);
-       if (do_nonshared)
+       release_resource(seg->res);
+       if (do_nonshared) {
                dcss_command = DCSS_LOADNSR;
-       else
-       dcss_command = DCSS_LOADNOLY;
+               seg->res->flags &= ~IORESOURCE_READONLY;
+       } else {
+               dcss_command = DCSS_LOADNOLY;
+               if (seg->vm_segtype == SEG_TYPE_SR ||
+                   seg->vm_segtype == SEG_TYPE_ER)
+                       seg->res->flags |= IORESOURCE_READONLY;
+       }
+       if (request_resource(&iomem_resource, seg->res)) {
+               PRINT_WARN("segment_modify_shared: could not reload segment %s"
+                          " - overlapping resources\n", name);
+               rc = -EBUSY;
+               kfree(seg->res);
+               goto out_del;
+       }
+       dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
        diag_cc = dcss_diag(dcss_command, seg->dcss_name,
                        &seg->start_addr, &seg->end);
        if (diag_cc > 1) {
@@ -446,9 +488,9 @@ segment_modify_shared (char *name, int do_nonshared)
        rc = 0;
        goto out_unlock;
  out_del:
+       remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
        list_del(&seg->list);
-       dcss_diag(DCSS_PURGESEG, seg->dcss_name,
-                 &dummy, &dummy);
+       dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
        kfree(seg);
  out_unlock:
        mutex_unlock(&dcss_lock);
@@ -478,6 +520,8 @@ segment_unload(char *name)
        }
        if (atomic_dec_return(&seg->ref_count) != 0)
                goto out_unlock;
+       release_resource(seg->res);
+       kfree(seg->res);
        remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
        list_del(&seg->list);
        dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
index cd85e34d8703551bdb7fa640be56792bcf32eaf0..9ff143e87746b5ac0bf350c1496307c10506d123 100644 (file)
@@ -52,7 +52,7 @@ extern int sysctl_userprocess_debug;
 extern void die(const char *,struct pt_regs *,long);
 
 #ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
 int register_page_fault_notifier(struct notifier_block *nb)
 {
        return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
@@ -137,7 +137,9 @@ static int __check_access_register(struct pt_regs *regs, int error_code)
 
 /*
  * Check which address space the address belongs to.
- * Returns 1 for user space and 0 for kernel space.
+ * May return 1 or 2 for user space and 0 for kernel space.
+ * Returns 2 for user space in primary addressing mode with
+ * CONFIG_S390_EXEC_PROTECT on and kernel parameter noexec=on.
  */
 static inline int check_user_space(struct pt_regs *regs, int error_code)
 {
@@ -154,7 +156,7 @@ static inline int check_user_space(struct pt_regs *regs, int error_code)
                return __check_access_register(regs, error_code);
        if (descriptor == 2)
                return current->thread.mm_segment.ar4;
-       return descriptor != 0;
+       return ((descriptor != 0) ^ (switch_amode)) << s390_noexec;
 }
 
 /*
@@ -183,6 +185,77 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code,
        force_sig_info(SIGSEGV, &si, current);
 }
 
+#ifdef CONFIG_S390_EXEC_PROTECT
+extern long sys_sigreturn(struct pt_regs *regs);
+extern long sys_rt_sigreturn(struct pt_regs *regs);
+extern long sys32_sigreturn(struct pt_regs *regs);
+extern long sys32_rt_sigreturn(struct pt_regs *regs);
+
+static inline void do_sigreturn(struct mm_struct *mm, struct pt_regs *regs,
+                               int rt)
+{
+       up_read(&mm->mmap_sem);
+       clear_tsk_thread_flag(current, TIF_SINGLE_STEP);
+#ifdef CONFIG_COMPAT
+       if (test_tsk_thread_flag(current, TIF_31BIT)) {
+               if (rt)
+                       sys32_rt_sigreturn(regs);
+               else
+                       sys32_sigreturn(regs);
+               return;
+       }
+#endif /* CONFIG_COMPAT */
+       if (rt)
+               sys_rt_sigreturn(regs);
+       else
+               sys_sigreturn(regs);
+       return;
+}
+
+static int signal_return(struct mm_struct *mm, struct pt_regs *regs,
+                        unsigned long address, unsigned long error_code)
+{
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
+       u16 *instruction;
+       unsigned long pfn, uaddr = regs->psw.addr;
+
+       spin_lock(&mm->page_table_lock);
+       pgd = pgd_offset(mm, uaddr);
+       if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+               goto out_fault;
+       pmd = pmd_offset(pgd, uaddr);
+       if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+               goto out_fault;
+       pte = pte_offset_map(pmd_offset(pgd_offset(mm, uaddr), uaddr), uaddr);
+       if (!pte || !pte_present(*pte))
+               goto out_fault;
+       pfn = pte_pfn(*pte);
+       if (!pfn_valid(pfn))
+               goto out_fault;
+       spin_unlock(&mm->page_table_lock);
+
+       instruction = (u16 *) ((pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE-1)));
+       if (*instruction == 0x0a77)
+               do_sigreturn(mm, regs, 0);
+       else if (*instruction == 0x0aad)
+               do_sigreturn(mm, regs, 1);
+       else {
+               printk("- XXX - do_exception: task = %s, primary, NO EXEC "
+                      "-> SIGSEGV\n", current->comm);
+               up_read(&mm->mmap_sem);
+               current->thread.prot_addr = address;
+               current->thread.trap_no = error_code;
+               do_sigsegv(regs, error_code, SEGV_MAPERR, address);
+       }
+       return 0;
+out_fault:
+       spin_unlock(&mm->page_table_lock);
+       return -EFAULT;
+}
+#endif /* CONFIG_S390_EXEC_PROTECT */
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -260,6 +333,17 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
         vma = find_vma(mm, address);
         if (!vma)
                 goto bad_area;
+
+#ifdef CONFIG_S390_EXEC_PROTECT
+       if (unlikely((user_address == 2) && !(vma->vm_flags & VM_EXEC)))
+               if (!signal_return(mm, regs, address, error_code))
+                       /*
+                        * signal_return() has done an up_read(&mm->mmap_sem)
+                        * if it returns 0.
+                        */
+                       return;
+#endif
+
         if (vma->vm_start <= address) 
                 goto good_area;
         if (!(vma->vm_flags & VM_GROWSDOWN))
@@ -452,8 +536,7 @@ void pfault_fini(void)
                : : "a" (&refbk), "m" (refbk) : "cc");
 }
 
-asmlinkage void
-pfault_interrupt(__u16 error_code)
+static void pfault_interrupt(__u16 error_code)
 {
        struct task_struct *tsk;
        __u16 subcode;
index 4bb21be3b00709bf6f0dbea0ae3d06686d209d81..b3e7c45efb63110f064ab77693e5349b71d081de 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/bootmem.h>
 #include <linux/pfn.h>
 #include <linux/poison.h>
-
+#include <linux/initrd.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -95,20 +95,18 @@ static void __init setup_ro_region(void)
        pte_t new_pte;
        unsigned long address, end;
 
-       address = ((unsigned long)&__start_rodata) & PAGE_MASK;
-       end = PFN_ALIGN((unsigned long)&__end_rodata);
+       address = ((unsigned long)&_stext) & PAGE_MASK;
+       end = PFN_ALIGN((unsigned long)&_eshared);
 
        for (; address < end; address += PAGE_SIZE) {
                pgd = pgd_offset_k(address);
                pmd = pmd_offset(pgd, address);
                pte = pte_offset_kernel(pmd, address);
                new_pte = mk_pte_phys(address, __pgprot(_PAGE_RO));
-               set_pte(pte, new_pte);
+               *pte = new_pte;
        }
 }
 
-extern void vmem_map_init(void);
-
 /*
  * paging_init() sets up the page tables
  */
@@ -125,11 +123,11 @@ void __init paging_init(void)
 #ifdef CONFIG_64BIT
        pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE;
        for (i = 0; i < PTRS_PER_PGD; i++)
-               pgd_clear(pg_dir + i);
+               pgd_clear_kernel(pg_dir + i);
 #else
        pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
        for (i = 0; i < PTRS_PER_PGD; i++)
-               pmd_clear((pmd_t *)(pg_dir + i));
+               pmd_clear_kernel((pmd_t *)(pg_dir + i));
 #endif
        vmem_map_init();
        setup_ro_region();
@@ -174,10 +172,8 @@ void __init mem_init(void)
                 datasize >>10,
                 initsize >> 10);
        printk("Write protected kernel read-only data: %#lx - %#lx\n",
-              (unsigned long)&__start_rodata,
-              PFN_ALIGN((unsigned long)&__end_rodata) - 1);
-       printk("Virtual memmap size: %ldk\n",
-              (max_pfn * sizeof(struct page)) >> 10);
+              (unsigned long)&_stext,
+              PFN_ALIGN((unsigned long)&_eshared) - 1);
 }
 
 void free_initmem(void)
index cd3d93e8c21171de4514aad283d23513ad2ef6ac..92a565190028618e603a067802faa4c7a4caabe3 100644 (file)
@@ -82,7 +82,7 @@ static inline pmd_t *vmem_pmd_alloc(void)
        if (!pmd)
                return NULL;
        for (i = 0; i < PTRS_PER_PMD; i++)
-               pmd_clear(pmd + i);
+               pmd_clear_kernel(pmd + i);
        return pmd;
 }
 
@@ -97,7 +97,7 @@ static inline pte_t *vmem_pte_alloc(void)
                return NULL;
        pte_val(empty_pte) = _PAGE_TYPE_EMPTY;
        for (i = 0; i < PTRS_PER_PTE; i++)
-               set_pte(pte + i, empty_pte);
+               pte[i] = empty_pte;
        return pte;
 }
 
@@ -119,7 +119,7 @@ static int vmem_add_range(unsigned long start, unsigned long size)
                        pm_dir = vmem_pmd_alloc();
                        if (!pm_dir)
                                goto out;
-                       pgd_populate(&init_mm, pg_dir, pm_dir);
+                       pgd_populate_kernel(&init_mm, pg_dir, pm_dir);
                }
 
                pm_dir = pmd_offset(pg_dir, address);
@@ -132,7 +132,7 @@ static int vmem_add_range(unsigned long start, unsigned long size)
 
                pt_dir = pte_offset_kernel(pm_dir, address);
                pte = pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL);
-               set_pte(pt_dir, pte);
+               *pt_dir = pte;
        }
        ret = 0;
 out:
@@ -161,7 +161,7 @@ static void vmem_remove_range(unsigned long start, unsigned long size)
                if (pmd_none(*pm_dir))
                        continue;
                pt_dir = pte_offset_kernel(pm_dir, address);
-               set_pte(pt_dir, pte);
+               *pt_dir = pte;
        }
        flush_tlb_kernel_range(start, start + size);
 }
@@ -191,7 +191,7 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
                        pm_dir = vmem_pmd_alloc();
                        if (!pm_dir)
                                goto out;
-                       pgd_populate(&init_mm, pg_dir, pm_dir);
+                       pgd_populate_kernel(&init_mm, pg_dir, pm_dir);
                }
 
                pm_dir = pmd_offset(pg_dir, address);
@@ -210,7 +210,7 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
                        if (!new_page)
                                goto out;
                        pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL);
-                       set_pte(pt_dir, pte);
+                       *pt_dir = pte;
                }
        }
        ret = 0;
index 697f0aa794b960a663b15ee09e161f86890119ab..eb18be5a656979b6415b3f7102c6f93b8fa07a2c 100644 (file)
@@ -29,7 +29,7 @@ struct dma_mapping_ops swiotlb_dma_ops = {
        .dma_supported = NULL,
 };
 
-void pci_swiotlb_init(void)
+void __init pci_swiotlb_init(void)
 {
        /* don't initialize swiotlb if iommu=off (no_iommu=1) */
        if (!iommu_detected && !no_iommu && end_pfn > MAX_DMA32_PFN)
index 92ba249f3a5bf6bfc64d4aca0200ad9812bac999..918b4d845f935ba5dfa4be45f88134716845a7e5 100644 (file)
@@ -74,14 +74,6 @@ 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 S390
-       select CRYPTO_ALGAPI
-       help
-         This is the s390 hardware accelerated implementation of the
-         SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
-
 config CRYPTO_SHA256
        tristate "SHA256 digest algorithm"
        select CRYPTO_ALGAPI
@@ -91,17 +83,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 S390
-       select CRYPTO_ALGAPI
-       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"
        select CRYPTO_ALGAPI
@@ -187,14 +168,6 @@ 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 S390
-       select CRYPTO_ALGAPI
-       select CRYPTO_BLKCIPHER
-       help
-         DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
-
 config CRYPTO_BLOWFISH
        tristate "Blowfish cipher algorithm"
        select CRYPTO_ALGAPI
@@ -336,28 +309,6 @@ config CRYPTO_AES_X86_64
 
          See <http://csrc.nist.gov/encryption/aes/> for more information.
 
-config CRYPTO_AES_S390
-       tristate "AES cipher algorithms (s390)"
-       depends on S390
-       select CRYPTO_ALGAPI
-       select CRYPTO_BLKCIPHER
-       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"
        select CRYPTO_ALGAPI
index 879250d3d0690d40191dad3699ab139820894552..ff8c4beaace41577ad384a171a63966e992b01e0 100644 (file)
@@ -51,6 +51,8 @@ config CRYPTO_DEV_PADLOCK_SHA
          If unsure say M. The compiled module will be
          called padlock-sha.ko
 
+source "arch/s390/crypto/Kconfig"
+
 config CRYPTO_DEV_GEODE
        tristate "Support for the Geode LX AES engine"
        depends on CRYPTO && X86_32 && PCI
index ec796ad087df1e274e37dfd4bd04c20ca864b39b..850788f4dd2ee789d3cdd5cd9e08313d6620773d 100644 (file)
@@ -22,5 +22,19 @@ config HID
 
          If unsure, say Y
 
+config HID_DEBUG
+       bool "HID debugging support"
+       depends on HID
+       ---help---
+       This option lets the HID layer output diagnostics about its internal
+       state, resolve HID usages, dump HID fields, etc. Individual HID drivers
+       use this debugging facility to output information about individual HID
+       devices, etc.
+
+       This feature is useful for those who are either debugging the HID parser
+       or any HID hardware device.
+
+       If unsure, say N
+
 endmenu
 
index 6432392110bfee17d5a1acaadb41efa0f79b8db0..52e97d8f3c95770427a7475c4efa64661bf38fc6 100644 (file)
@@ -1,15 +1,8 @@
 #
 # Makefile for the HID driver
 #
-
-# Multipart objects.
-hid-objs       := hid-core.o hid-input.o
-
-# Optional parts of multipart objects.
+hid-objs                       := hid-core.o hid-input.o
 
 obj-$(CONFIG_HID)              += hid.o
-
-ifeq ($(CONFIG_INPUT_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+hid-$(CONFIG_HID_DEBUG)                += hid-debug.o
 
index 49f18f5b2514adbae5b545df07094771c9bb1f40..8c7d48eff7b7a6339db159b901987e5ca12c3815 100644 (file)
 #include <linux/input.h>
 #include <linux/wait.h>
 
-#undef DEBUG
-#undef DEBUG_DATA
-
 #include <linux/hid.h>
 #include <linux/hiddev.h>
+#include <linux/hid-debug.h>
 
 /*
  * Version Information
@@ -951,7 +949,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
                return -1;
        }
 
-#ifdef DEBUG_DATA
+#ifdef CONFIG_HID_DEBUG
        printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
 #endif
 
@@ -961,7 +959,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i
                size--;
        }
 
-#ifdef DEBUG_DATA
+#ifdef CONFIG_HID_DEBUG
        {
                int i;
                printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
new file mode 100644 (file)
index 0000000..89241be
--- /dev/null
@@ -0,0 +1,764 @@
+/*
+ * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
+ *
+ *  (c) 1999 Andreas Gal               <gal@cs.uni-magdeburg.de>
+ *  (c) 2000-2001 Vojtech Pavlik       <vojtech@ucw.cz>
+ *  (c) 2007 Jiri Kosina
+ *
+ *  Some debug stuff for the HID parser.
+ */
+
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/hid.h>
+
+struct hid_usage_entry {
+       unsigned  page;
+       unsigned  usage;
+       char     *description;
+};
+
+static const struct hid_usage_entry hid_usage_table[] = {
+  {  0,      0, "Undefined" },
+  {  1,      0, "GenericDesktop" },
+    {0, 0x01, "Pointer"},
+    {0, 0x02, "Mouse"},
+    {0, 0x04, "Joystick"},
+    {0, 0x05, "GamePad"},
+    {0, 0x06, "Keyboard"},
+    {0, 0x07, "Keypad"},
+    {0, 0x08, "MultiAxis"},
+      {0, 0x30, "X"},
+      {0, 0x31, "Y"},
+      {0, 0x32, "Z"},
+      {0, 0x33, "Rx"},
+      {0, 0x34, "Ry"},
+      {0, 0x35, "Rz"},
+      {0, 0x36, "Slider"},
+      {0, 0x37, "Dial"},
+      {0, 0x38, "Wheel"},
+      {0, 0x39, "HatSwitch"},
+    {0, 0x3a, "CountedBuffer"},
+      {0, 0x3b, "ByteCount"},
+      {0, 0x3c, "MotionWakeup"},
+      {0, 0x3d, "Start"},
+      {0, 0x3e, "Select"},
+      {0, 0x40, "Vx"},
+      {0, 0x41, "Vy"},
+      {0, 0x42, "Vz"},
+      {0, 0x43, "Vbrx"},
+      {0, 0x44, "Vbry"},
+      {0, 0x45, "Vbrz"},
+      {0, 0x46, "Vno"},
+    {0, 0x80, "SystemControl"},
+      {0, 0x81, "SystemPowerDown"},
+      {0, 0x82, "SystemSleep"},
+      {0, 0x83, "SystemWakeUp"},
+      {0, 0x84, "SystemContextMenu"},
+      {0, 0x85, "SystemMainMenu"},
+      {0, 0x86, "SystemAppMenu"},
+      {0, 0x87, "SystemMenuHelp"},
+      {0, 0x88, "SystemMenuExit"},
+      {0, 0x89, "SystemMenuSelect"},
+      {0, 0x8a, "SystemMenuRight"},
+      {0, 0x8b, "SystemMenuLeft"},
+      {0, 0x8c, "SystemMenuUp"},
+      {0, 0x8d, "SystemMenuDown"},
+      {0, 0x90, "D-PadUp"},
+      {0, 0x91, "D-PadDown"},
+      {0, 0x92, "D-PadRight"},
+      {0, 0x93, "D-PadLeft"},
+  {  2, 0, "Simulation" },
+      {0, 0xb0, "Aileron"},
+      {0, 0xb1, "AileronTrim"},
+      {0, 0xb2, "Anti-Torque"},
+      {0, 0xb3, "Autopilot"},
+      {0, 0xb4, "Chaff"},
+      {0, 0xb5, "Collective"},
+      {0, 0xb6, "DiveBrake"},
+      {0, 0xb7, "ElectronicCountermeasures"},
+      {0, 0xb8, "Elevator"},
+      {0, 0xb9, "ElevatorTrim"},
+      {0, 0xba, "Rudder"},
+      {0, 0xbb, "Throttle"},
+      {0, 0xbc, "FlightCommunications"},
+      {0, 0xbd, "FlareRelease"},
+      {0, 0xbe, "LandingGear"},
+      {0, 0xbf, "ToeBrake"},
+  {  7, 0, "Keyboard" },
+  {  8, 0, "LED" },
+      {0, 0x01, "NumLock"},
+      {0, 0x02, "CapsLock"},
+      {0, 0x03, "ScrollLock"},
+      {0, 0x04, "Compose"},
+      {0, 0x05, "Kana"},
+      {0, 0x4b, "GenericIndicator"},
+  {  9, 0, "Button" },
+  { 10, 0, "Ordinal" },
+  { 12, 0, "Consumer" },
+      {0, 0x238, "HorizontalWheel"},
+  { 13, 0, "Digitizers" },
+    {0, 0x01, "Digitizer"},
+    {0, 0x02, "Pen"},
+    {0, 0x03, "LightPen"},
+    {0, 0x04, "TouchScreen"},
+    {0, 0x05, "TouchPad"},
+    {0, 0x20, "Stylus"},
+    {0, 0x21, "Puck"},
+    {0, 0x22, "Finger"},
+    {0, 0x30, "TipPressure"},
+    {0, 0x31, "BarrelPressure"},
+    {0, 0x32, "InRange"},
+    {0, 0x33, "Touch"},
+    {0, 0x34, "UnTouch"},
+    {0, 0x35, "Tap"},
+    {0, 0x39, "TabletFunctionKey"},
+    {0, 0x3a, "ProgramChangeKey"},
+    {0, 0x3c, "Invert"},
+    {0, 0x42, "TipSwitch"},
+    {0, 0x43, "SecondaryTipSwitch"},
+    {0, 0x44, "BarrelSwitch"},
+    {0, 0x45, "Eraser"},
+    {0, 0x46, "TabletPick"},
+  { 15, 0, "PhysicalInterfaceDevice" },
+    {0, 0x00, "Undefined"},
+    {0, 0x01, "Physical_Interface_Device"},
+      {0, 0x20, "Normal"},
+    {0, 0x21, "Set_Effect_Report"},
+      {0, 0x22, "Effect_Block_Index"},
+      {0, 0x23, "Parameter_Block_Offset"},
+      {0, 0x24, "ROM_Flag"},
+      {0, 0x25, "Effect_Type"},
+        {0, 0x26, "ET_Constant_Force"},
+        {0, 0x27, "ET_Ramp"},
+        {0, 0x28, "ET_Custom_Force_Data"},
+        {0, 0x30, "ET_Square"},
+        {0, 0x31, "ET_Sine"},
+        {0, 0x32, "ET_Triangle"},
+        {0, 0x33, "ET_Sawtooth_Up"},
+        {0, 0x34, "ET_Sawtooth_Down"},
+        {0, 0x40, "ET_Spring"},
+        {0, 0x41, "ET_Damper"},
+        {0, 0x42, "ET_Inertia"},
+        {0, 0x43, "ET_Friction"},
+      {0, 0x50, "Duration"},
+      {0, 0x51, "Sample_Period"},
+      {0, 0x52, "Gain"},
+      {0, 0x53, "Trigger_Button"},
+      {0, 0x54, "Trigger_Repeat_Interval"},
+      {0, 0x55, "Axes_Enable"},
+        {0, 0x56, "Direction_Enable"},
+      {0, 0x57, "Direction"},
+      {0, 0x58, "Type_Specific_Block_Offset"},
+        {0, 0x59, "Block_Type"},
+        {0, 0x5A, "Set_Envelope_Report"},
+          {0, 0x5B, "Attack_Level"},
+          {0, 0x5C, "Attack_Time"},
+          {0, 0x5D, "Fade_Level"},
+          {0, 0x5E, "Fade_Time"},
+        {0, 0x5F, "Set_Condition_Report"},
+        {0, 0x60, "CP_Offset"},
+        {0, 0x61, "Positive_Coefficient"},
+        {0, 0x62, "Negative_Coefficient"},
+        {0, 0x63, "Positive_Saturation"},
+        {0, 0x64, "Negative_Saturation"},
+        {0, 0x65, "Dead_Band"},
+      {0, 0x66, "Download_Force_Sample"},
+      {0, 0x67, "Isoch_Custom_Force_Enable"},
+      {0, 0x68, "Custom_Force_Data_Report"},
+        {0, 0x69, "Custom_Force_Data"},
+        {0, 0x6A, "Custom_Force_Vendor_Defined_Data"},
+      {0, 0x6B, "Set_Custom_Force_Report"},
+        {0, 0x6C, "Custom_Force_Data_Offset"},
+        {0, 0x6D, "Sample_Count"},
+      {0, 0x6E, "Set_Periodic_Report"},
+        {0, 0x6F, "Offset"},
+        {0, 0x70, "Magnitude"},
+        {0, 0x71, "Phase"},
+        {0, 0x72, "Period"},
+      {0, 0x73, "Set_Constant_Force_Report"},
+        {0, 0x74, "Set_Ramp_Force_Report"},
+        {0, 0x75, "Ramp_Start"},
+        {0, 0x76, "Ramp_End"},
+      {0, 0x77, "Effect_Operation_Report"},
+        {0, 0x78, "Effect_Operation"},
+          {0, 0x79, "Op_Effect_Start"},
+          {0, 0x7A, "Op_Effect_Start_Solo"},
+          {0, 0x7B, "Op_Effect_Stop"},
+          {0, 0x7C, "Loop_Count"},
+      {0, 0x7D, "Device_Gain_Report"},
+        {0, 0x7E, "Device_Gain"},
+    {0, 0x7F, "PID_Pool_Report"},
+      {0, 0x80, "RAM_Pool_Size"},
+      {0, 0x81, "ROM_Pool_Size"},
+      {0, 0x82, "ROM_Effect_Block_Count"},
+      {0, 0x83, "Simultaneous_Effects_Max"},
+      {0, 0x84, "Pool_Alignment"},
+    {0, 0x85, "PID_Pool_Move_Report"},
+      {0, 0x86, "Move_Source"},
+      {0, 0x87, "Move_Destination"},
+      {0, 0x88, "Move_Length"},
+    {0, 0x89, "PID_Block_Load_Report"},
+      {0, 0x8B, "Block_Load_Status"},
+      {0, 0x8C, "Block_Load_Success"},
+      {0, 0x8D, "Block_Load_Full"},
+      {0, 0x8E, "Block_Load_Error"},
+      {0, 0x8F, "Block_Handle"},
+      {0, 0x90, "PID_Block_Free_Report"},
+      {0, 0x91, "Type_Specific_Block_Handle"},
+    {0, 0x92, "PID_State_Report"},
+      {0, 0x94, "Effect_Playing"},
+      {0, 0x95, "PID_Device_Control_Report"},
+        {0, 0x96, "PID_Device_Control"},
+        {0, 0x97, "DC_Enable_Actuators"},
+        {0, 0x98, "DC_Disable_Actuators"},
+        {0, 0x99, "DC_Stop_All_Effects"},
+        {0, 0x9A, "DC_Device_Reset"},
+        {0, 0x9B, "DC_Device_Pause"},
+        {0, 0x9C, "DC_Device_Continue"},
+      {0, 0x9F, "Device_Paused"},
+      {0, 0xA0, "Actuators_Enabled"},
+      {0, 0xA4, "Safety_Switch"},
+      {0, 0xA5, "Actuator_Override_Switch"},
+      {0, 0xA6, "Actuator_Power"},
+    {0, 0xA7, "Start_Delay"},
+    {0, 0xA8, "Parameter_Block_Size"},
+    {0, 0xA9, "Device_Managed_Pool"},
+    {0, 0xAA, "Shared_Parameter_Blocks"},
+    {0, 0xAB, "Create_New_Effect_Report"},
+    {0, 0xAC, "RAM_Pool_Available"},
+  { 0x84, 0, "Power Device" },
+    { 0x84, 0x02, "PresentStatus" },
+    { 0x84, 0x03, "ChangeStatus" },
+    { 0x84, 0x04, "UPS" },
+    { 0x84, 0x05, "PowerSupply" },
+    { 0x84, 0x10, "BatterySystem" },
+    { 0x84, 0x11, "BatterySystemID" },
+    { 0x84, 0x12, "Battery" },
+    { 0x84, 0x13, "BatteryID" },
+    { 0x84, 0x14, "Charger" },
+    { 0x84, 0x15, "ChargerID" },
+    { 0x84, 0x16, "PowerConverter" },
+    { 0x84, 0x17, "PowerConverterID" },
+    { 0x84, 0x18, "OutletSystem" },
+    { 0x84, 0x19, "OutletSystemID" },
+    { 0x84, 0x1a, "Input" },
+    { 0x84, 0x1b, "InputID" },
+    { 0x84, 0x1c, "Output" },
+    { 0x84, 0x1d, "OutputID" },
+    { 0x84, 0x1e, "Flow" },
+    { 0x84, 0x1f, "FlowID" },
+    { 0x84, 0x20, "Outlet" },
+    { 0x84, 0x21, "OutletID" },
+    { 0x84, 0x22, "Gang" },
+    { 0x84, 0x24, "PowerSummary" },
+    { 0x84, 0x25, "PowerSummaryID" },
+    { 0x84, 0x30, "Voltage" },
+    { 0x84, 0x31, "Current" },
+    { 0x84, 0x32, "Frequency" },
+    { 0x84, 0x33, "ApparentPower" },
+    { 0x84, 0x35, "PercentLoad" },
+    { 0x84, 0x40, "ConfigVoltage" },
+    { 0x84, 0x41, "ConfigCurrent" },
+    { 0x84, 0x43, "ConfigApparentPower" },
+    { 0x84, 0x53, "LowVoltageTransfer" },
+    { 0x84, 0x54, "HighVoltageTransfer" },
+    { 0x84, 0x56, "DelayBeforeStartup" },
+    { 0x84, 0x57, "DelayBeforeShutdown" },
+    { 0x84, 0x58, "Test" },
+    { 0x84, 0x5a, "AudibleAlarmControl" },
+    { 0x84, 0x60, "Present" },
+    { 0x84, 0x61, "Good" },
+    { 0x84, 0x62, "InternalFailure" },
+    { 0x84, 0x65, "Overload" },
+    { 0x84, 0x66, "OverCharged" },
+    { 0x84, 0x67, "OverTemperature" },
+    { 0x84, 0x68, "ShutdownRequested" },
+    { 0x84, 0x69, "ShutdownImminent" },
+    { 0x84, 0x6b, "SwitchOn/Off" },
+    { 0x84, 0x6c, "Switchable" },
+    { 0x84, 0x6d, "Used" },
+    { 0x84, 0x6e, "Boost" },
+    { 0x84, 0x73, "CommunicationLost" },
+    { 0x84, 0xfd, "iManufacturer" },
+    { 0x84, 0xfe, "iProduct" },
+    { 0x84, 0xff, "iSerialNumber" },
+  { 0x85, 0, "Battery System" },
+    { 0x85, 0x01, "SMBBatteryMode" },
+    { 0x85, 0x02, "SMBBatteryStatus" },
+    { 0x85, 0x03, "SMBAlarmWarning" },
+    { 0x85, 0x04, "SMBChargerMode" },
+    { 0x85, 0x05, "SMBChargerStatus" },
+    { 0x85, 0x06, "SMBChargerSpecInfo" },
+    { 0x85, 0x07, "SMBSelectorState" },
+    { 0x85, 0x08, "SMBSelectorPresets" },
+    { 0x85, 0x09, "SMBSelectorInfo" },
+    { 0x85, 0x29, "RemainingCapacityLimit" },
+    { 0x85, 0x2c, "CapacityMode" },
+    { 0x85, 0x42, "BelowRemainingCapacityLimit" },
+    { 0x85, 0x44, "Charging" },
+    { 0x85, 0x45, "Discharging" },
+    { 0x85, 0x4b, "NeedReplacement" },
+    { 0x85, 0x66, "RemainingCapacity" },
+    { 0x85, 0x68, "RunTimeToEmpty" },
+    { 0x85, 0x6a, "AverageTimeToFull" },
+    { 0x85, 0x83, "DesignCapacity" },
+    { 0x85, 0x85, "ManufacturerDate" },
+    { 0x85, 0x89, "iDeviceChemistry" },
+    { 0x85, 0x8b, "Rechargable" },
+    { 0x85, 0x8f, "iOEMInformation" },
+    { 0x85, 0x8d, "CapacityGranularity1" },
+    { 0x85, 0xd0, "ACPresent" },
+  /* pages 0xff00 to 0xffff are vendor-specific */
+  { 0xffff, 0, "Vendor-specific-FF" },
+  { 0, 0, NULL }
+};
+
+static void resolv_usage_page(unsigned page) {
+       const struct hid_usage_entry *p;
+
+       for (p = hid_usage_table; p->description; p++)
+               if (p->page == page) {
+                       printk("%s", p->description);
+                       return;
+               }
+       printk("%04x", page);
+}
+
+void hid_resolv_usage(unsigned usage) {
+       const struct hid_usage_entry *p;
+
+       resolv_usage_page(usage >> 16);
+       printk(".");
+       for (p = hid_usage_table; p->description; p++)
+               if (p->page == (usage >> 16)) {
+                       for(++p; p->description && p->usage != 0; p++)
+                               if (p->usage == (usage & 0xffff)) {
+                                       printk("%s", p->description);
+                                       return;
+                               }
+                       break;
+               }
+       printk("%04x", usage & 0xffff);
+}
+EXPORT_SYMBOL_GPL(hid_resolv_usage);
+
+__inline__ static void tab(int n) {
+       while (n--) printk(" ");
+}
+
+void hid_dump_field(struct hid_field *field, int n) {
+       int j;
+
+       if (field->physical) {
+               tab(n);
+               printk("Physical(");
+               hid_resolv_usage(field->physical); printk(")\n");
+       }
+       if (field->logical) {
+               tab(n);
+               printk("Logical(");
+               hid_resolv_usage(field->logical); printk(")\n");
+       }
+       tab(n); printk("Usage(%d)\n", field->maxusage);
+       for (j = 0; j < field->maxusage; j++) {
+               tab(n+2); hid_resolv_usage(field->usage[j].hid); printk("\n");
+       }
+       if (field->logical_minimum != field->logical_maximum) {
+               tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
+               tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
+       }
+       if (field->physical_minimum != field->physical_maximum) {
+               tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
+               tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
+       }
+       if (field->unit_exponent) {
+               tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
+       }
+       if (field->unit) {
+               char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
+               char *units[5][8] = {
+                       { "None", "None", "None", "None", "None", "None", "None", "None" },
+                       { "None", "Centimeter", "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
+                       { "None", "Radians",    "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
+                       { "None", "Inch",       "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" },
+                       { "None", "Degrees",    "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }
+               };
+
+               int i;
+               int sys;
+                __u32 data = field->unit;
+
+               /* First nibble tells us which system we're in. */
+               sys = data & 0xf;
+               data >>= 4;
+
+               if(sys > 4) {
+                       tab(n); printk("Unit(Invalid)\n");
+               }
+               else {
+                       int earlier_unit = 0;
+
+                       tab(n); printk("Unit(%s : ", systems[sys]);
+
+                       for (i=1 ; i<sizeof(__u32)*2 ; i++) {
+                               char nibble = data & 0xf;
+                               data >>= 4;
+                               if (nibble != 0) {
+                                       if(earlier_unit++ > 0)
+                                               printk("*");
+                                       printk("%s", units[sys][i]);
+                                       if(nibble != 1) {
+                                               /* This is a _signed_ nibble(!) */
+
+                                               int val = nibble & 0x7;
+                                               if(nibble & 0x08)
+                                                       val = -((0x7 & ~val) +1);
+                                               printk("^%d", val);
+                                       }
+                               }
+                       }
+                       printk(")\n");
+               }
+       }
+       tab(n); printk("Report Size(%u)\n", field->report_size);
+       tab(n); printk("Report Count(%u)\n", field->report_count);
+       tab(n); printk("Report Offset(%u)\n", field->report_offset);
+
+       tab(n); printk("Flags( ");
+       j = field->flags;
+       printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
+       printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
+       printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
+       printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
+       printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
+       printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : "");
+       printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
+       printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
+       printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
+       printk(")\n");
+}
+EXPORT_SYMBOL_GPL(hid_dump_field);
+
+void hid_dump_device(struct hid_device *device) {
+       struct hid_report_enum *report_enum;
+       struct hid_report *report;
+       struct list_head *list;
+       unsigned i,k;
+       static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
+
+       for (i = 0; i < HID_REPORT_TYPES; i++) {
+               report_enum = device->report_enum + i;
+               list = report_enum->report_list.next;
+               while (list != &report_enum->report_list) {
+                       report = (struct hid_report *) list;
+                       tab(2);
+                       printk("%s", table[i]);
+                       if (report->id)
+                               printk("(%d)", report->id);
+                       printk("[%s]", table[report->type]);
+                       printk("\n");
+                       for (k = 0; k < report->maxfield; k++) {
+                               tab(4);
+                               printk("Field(%d)\n", k);
+                               hid_dump_field(report->field[k], 6);
+                       }
+                       list = list->next;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(hid_dump_device);
+
+void hid_dump_input(struct hid_usage *usage, __s32 value) {
+       printk("hid-debug: input ");
+       hid_resolv_usage(usage->hid);
+       printk(" = %d\n", value);
+}
+EXPORT_SYMBOL_GPL(hid_dump_input);
+
+static char *events[EV_MAX + 1] = {
+       [EV_SYN] = "Sync",                      [EV_KEY] = "Key",
+       [EV_REL] = "Relative",                  [EV_ABS] = "Absolute",
+       [EV_MSC] = "Misc",                      [EV_LED] = "LED",
+       [EV_SND] = "Sound",                     [EV_REP] = "Repeat",
+       [EV_FF] = "ForceFeedback",              [EV_PWR] = "Power",
+       [EV_FF_STATUS] = "ForceFeedbackStatus",
+};
+
+static char *syncs[2] = {
+       [SYN_REPORT] = "Report",                [SYN_CONFIG] = "Config",
+};
+static char *keys[KEY_MAX + 1] = {
+       [KEY_RESERVED] = "Reserved",            [KEY_ESC] = "Esc",
+       [KEY_1] = "1",                          [KEY_2] = "2",
+       [KEY_3] = "3",                          [KEY_4] = "4",
+       [KEY_5] = "5",                          [KEY_6] = "6",
+       [KEY_7] = "7",                          [KEY_8] = "8",
+       [KEY_9] = "9",                          [KEY_0] = "0",
+       [KEY_MINUS] = "Minus",                  [KEY_EQUAL] = "Equal",
+       [KEY_BACKSPACE] = "Backspace",          [KEY_TAB] = "Tab",
+       [KEY_Q] = "Q",                          [KEY_W] = "W",
+       [KEY_E] = "E",                          [KEY_R] = "R",
+       [KEY_T] = "T",                          [KEY_Y] = "Y",
+       [KEY_U] = "U",                          [KEY_I] = "I",
+       [KEY_O] = "O",                          [KEY_P] = "P",
+       [KEY_LEFTBRACE] = "LeftBrace",          [KEY_RIGHTBRACE] = "RightBrace",
+       [KEY_ENTER] = "Enter",                  [KEY_LEFTCTRL] = "LeftControl",
+       [KEY_A] = "A",                          [KEY_S] = "S",
+       [KEY_D] = "D",                          [KEY_F] = "F",
+       [KEY_G] = "G",                          [KEY_H] = "H",
+       [KEY_J] = "J",                          [KEY_K] = "K",
+       [KEY_L] = "L",                          [KEY_SEMICOLON] = "Semicolon",
+       [KEY_APOSTROPHE] = "Apostrophe",        [KEY_GRAVE] = "Grave",
+       [KEY_LEFTSHIFT] = "LeftShift",          [KEY_BACKSLASH] = "BackSlash",
+       [KEY_Z] = "Z",                          [KEY_X] = "X",
+       [KEY_C] = "C",                          [KEY_V] = "V",
+       [KEY_B] = "B",                          [KEY_N] = "N",
+       [KEY_M] = "M",                          [KEY_COMMA] = "Comma",
+       [KEY_DOT] = "Dot",                      [KEY_SLASH] = "Slash",
+       [KEY_RIGHTSHIFT] = "RightShift",        [KEY_KPASTERISK] = "KPAsterisk",
+       [KEY_LEFTALT] = "LeftAlt",              [KEY_SPACE] = "Space",
+       [KEY_CAPSLOCK] = "CapsLock",            [KEY_F1] = "F1",
+       [KEY_F2] = "F2",                        [KEY_F3] = "F3",
+       [KEY_F4] = "F4",                        [KEY_F5] = "F5",
+       [KEY_F6] = "F6",                        [KEY_F7] = "F7",
+       [KEY_F8] = "F8",                        [KEY_F9] = "F9",
+       [KEY_F10] = "F10",                      [KEY_NUMLOCK] = "NumLock",
+       [KEY_SCROLLLOCK] = "ScrollLock",        [KEY_KP7] = "KP7",
+       [KEY_KP8] = "KP8",                      [KEY_KP9] = "KP9",
+       [KEY_KPMINUS] = "KPMinus",              [KEY_KP4] = "KP4",
+       [KEY_KP5] = "KP5",                      [KEY_KP6] = "KP6",
+       [KEY_KPPLUS] = "KPPlus",                [KEY_KP1] = "KP1",
+       [KEY_KP2] = "KP2",                      [KEY_KP3] = "KP3",
+       [KEY_KP0] = "KP0",                      [KEY_KPDOT] = "KPDot",
+       [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
+       [KEY_F11] = "F11",                      [KEY_F12] = "F12",
+       [KEY_RO] = "RO",                        [KEY_KATAKANA] = "Katakana",
+       [KEY_HIRAGANA] = "HIRAGANA",            [KEY_HENKAN] = "Henkan",
+       [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan",
+       [KEY_KPJPCOMMA] = "KPJpComma",          [KEY_KPENTER] = "KPEnter",
+       [KEY_RIGHTCTRL] = "RightCtrl",          [KEY_KPSLASH] = "KPSlash",
+       [KEY_SYSRQ] = "SysRq",                  [KEY_RIGHTALT] = "RightAlt",
+       [KEY_LINEFEED] = "LineFeed",            [KEY_HOME] = "Home",
+       [KEY_UP] = "Up",                        [KEY_PAGEUP] = "PageUp",
+       [KEY_LEFT] = "Left",                    [KEY_RIGHT] = "Right",
+       [KEY_END] = "End",                      [KEY_DOWN] = "Down",
+       [KEY_PAGEDOWN] = "PageDown",            [KEY_INSERT] = "Insert",
+       [KEY_DELETE] = "Delete",                [KEY_MACRO] = "Macro",
+       [KEY_MUTE] = "Mute",                    [KEY_VOLUMEDOWN] = "VolumeDown",
+       [KEY_VOLUMEUP] = "VolumeUp",            [KEY_POWER] = "Power",
+       [KEY_KPEQUAL] = "KPEqual",              [KEY_KPPLUSMINUS] = "KPPlusMinus",
+       [KEY_PAUSE] = "Pause",                  [KEY_KPCOMMA] = "KPComma",
+       [KEY_HANGUEL] = "Hangeul",              [KEY_HANJA] = "Hanja",
+       [KEY_YEN] = "Yen",                      [KEY_LEFTMETA] = "LeftMeta",
+       [KEY_RIGHTMETA] = "RightMeta",          [KEY_COMPOSE] = "Compose",
+       [KEY_STOP] = "Stop",                    [KEY_AGAIN] = "Again",
+       [KEY_PROPS] = "Props",                  [KEY_UNDO] = "Undo",
+       [KEY_FRONT] = "Front",                  [KEY_COPY] = "Copy",
+       [KEY_OPEN] = "Open",                    [KEY_PASTE] = "Paste",
+       [KEY_FIND] = "Find",                    [KEY_CUT] = "Cut",
+       [KEY_HELP] = "Help",                    [KEY_MENU] = "Menu",
+       [KEY_CALC] = "Calc",                    [KEY_SETUP] = "Setup",
+       [KEY_SLEEP] = "Sleep",                  [KEY_WAKEUP] = "WakeUp",
+       [KEY_FILE] = "File",                    [KEY_SENDFILE] = "SendFile",
+       [KEY_DELETEFILE] = "DeleteFile",        [KEY_XFER] = "X-fer",
+       [KEY_PROG1] = "Prog1",                  [KEY_PROG2] = "Prog2",
+       [KEY_WWW] = "WWW",                      [KEY_MSDOS] = "MSDOS",
+       [KEY_COFFEE] = "Coffee",                [KEY_DIRECTION] = "Direction",
+       [KEY_CYCLEWINDOWS] = "CycleWindows",    [KEY_MAIL] = "Mail",
+       [KEY_BOOKMARKS] = "Bookmarks",          [KEY_COMPUTER] = "Computer",
+       [KEY_BACK] = "Back",                    [KEY_FORWARD] = "Forward",
+       [KEY_CLOSECD] = "CloseCD",              [KEY_EJECTCD] = "EjectCD",
+       [KEY_EJECTCLOSECD] = "EjectCloseCD",    [KEY_NEXTSONG] = "NextSong",
+       [KEY_PLAYPAUSE] = "PlayPause",          [KEY_PREVIOUSSONG] = "PreviousSong",
+       [KEY_STOPCD] = "StopCD",                [KEY_RECORD] = "Record",
+       [KEY_REWIND] = "Rewind",                [KEY_PHONE] = "Phone",
+       [KEY_ISO] = "ISOKey",                   [KEY_CONFIG] = "Config",
+       [KEY_HOMEPAGE] = "HomePage",            [KEY_REFRESH] = "Refresh",
+       [KEY_EXIT] = "Exit",                    [KEY_MOVE] = "Move",
+       [KEY_EDIT] = "Edit",                    [KEY_SCROLLUP] = "ScrollUp",
+       [KEY_SCROLLDOWN] = "ScrollDown",        [KEY_KPLEFTPAREN] = "KPLeftParenthesis",
+       [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New",
+       [KEY_REDO] = "Redo",                    [KEY_F13] = "F13",
+       [KEY_F14] = "F14",                      [KEY_F15] = "F15",
+       [KEY_F16] = "F16",                      [KEY_F17] = "F17",
+       [KEY_F18] = "F18",                      [KEY_F19] = "F19",
+       [KEY_F20] = "F20",                      [KEY_F21] = "F21",
+       [KEY_F22] = "F22",                      [KEY_F23] = "F23",
+       [KEY_F24] = "F24",                      [KEY_PLAYCD] = "PlayCD",
+       [KEY_PAUSECD] = "PauseCD",              [KEY_PROG3] = "Prog3",
+       [KEY_PROG4] = "Prog4",                  [KEY_SUSPEND] = "Suspend",
+       [KEY_CLOSE] = "Close",                  [KEY_PLAY] = "Play",
+       [KEY_FASTFORWARD] = "FastForward",      [KEY_BASSBOOST] = "BassBoost",
+       [KEY_PRINT] = "Print",                  [KEY_HP] = "HP",
+       [KEY_CAMERA] = "Camera",                [KEY_SOUND] = "Sound",
+       [KEY_QUESTION] = "Question",            [KEY_EMAIL] = "Email",
+       [KEY_CHAT] = "Chat",                    [KEY_SEARCH] = "Search",
+       [KEY_CONNECT] = "Connect",              [KEY_FINANCE] = "Finance",
+       [KEY_SPORT] = "Sport",                  [KEY_SHOP] = "Shop",
+       [KEY_ALTERASE] = "AlternateErase",      [KEY_CANCEL] = "Cancel",
+       [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
+       [KEY_MEDIA] = "Media",                  [KEY_UNKNOWN] = "Unknown",
+       [BTN_0] = "Btn0",                       [BTN_1] = "Btn1",
+       [BTN_2] = "Btn2",                       [BTN_3] = "Btn3",
+       [BTN_4] = "Btn4",                       [BTN_5] = "Btn5",
+       [BTN_6] = "Btn6",                       [BTN_7] = "Btn7",
+       [BTN_8] = "Btn8",                       [BTN_9] = "Btn9",
+       [BTN_LEFT] = "LeftBtn",                 [BTN_RIGHT] = "RightBtn",
+       [BTN_MIDDLE] = "MiddleBtn",             [BTN_SIDE] = "SideBtn",
+       [BTN_EXTRA] = "ExtraBtn",               [BTN_FORWARD] = "ForwardBtn",
+       [BTN_BACK] = "BackBtn",                 [BTN_TASK] = "TaskBtn",
+       [BTN_TRIGGER] = "Trigger",              [BTN_THUMB] = "ThumbBtn",
+       [BTN_THUMB2] = "ThumbBtn2",             [BTN_TOP] = "TopBtn",
+       [BTN_TOP2] = "TopBtn2",                 [BTN_PINKIE] = "PinkieBtn",
+       [BTN_BASE] = "BaseBtn",                 [BTN_BASE2] = "BaseBtn2",
+       [BTN_BASE3] = "BaseBtn3",               [BTN_BASE4] = "BaseBtn4",
+       [BTN_BASE5] = "BaseBtn5",               [BTN_BASE6] = "BaseBtn6",
+       [BTN_DEAD] = "BtnDead",                 [BTN_A] = "BtnA",
+       [BTN_B] = "BtnB",                       [BTN_C] = "BtnC",
+       [BTN_X] = "BtnX",                       [BTN_Y] = "BtnY",
+       [BTN_Z] = "BtnZ",                       [BTN_TL] = "BtnTL",
+       [BTN_TR] = "BtnTR",                     [BTN_TL2] = "BtnTL2",
+       [BTN_TR2] = "BtnTR2",                   [BTN_SELECT] = "BtnSelect",
+       [BTN_START] = "BtnStart",               [BTN_MODE] = "BtnMode",
+       [BTN_THUMBL] = "BtnThumbL",             [BTN_THUMBR] = "BtnThumbR",
+       [BTN_TOOL_PEN] = "ToolPen",             [BTN_TOOL_RUBBER] = "ToolRubber",
+       [BTN_TOOL_BRUSH] = "ToolBrush",         [BTN_TOOL_PENCIL] = "ToolPencil",
+       [BTN_TOOL_AIRBRUSH] = "ToolAirbrush",   [BTN_TOOL_FINGER] = "ToolFinger",
+       [BTN_TOOL_MOUSE] = "ToolMouse",         [BTN_TOOL_LENS] = "ToolLens",
+       [BTN_TOUCH] = "Touch",                  [BTN_STYLUS] = "Stylus",
+       [BTN_STYLUS2] = "Stylus2",              [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
+       [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
+       [BTN_GEAR_UP] = "Gear up",              [KEY_OK] = "Ok",
+       [KEY_SELECT] = "Select",                [KEY_GOTO] = "Goto",
+       [KEY_CLEAR] = "Clear",                  [KEY_POWER2] = "Power2",
+       [KEY_OPTION] = "Option",                [KEY_INFO] = "Info",
+       [KEY_TIME] = "Time",                    [KEY_VENDOR] = "Vendor",
+       [KEY_ARCHIVE] = "Archive",              [KEY_PROGRAM] = "Program",
+       [KEY_CHANNEL] = "Channel",              [KEY_FAVORITES] = "Favorites",
+       [KEY_EPG] = "EPG",                      [KEY_PVR] = "PVR",
+       [KEY_MHP] = "MHP",                      [KEY_LANGUAGE] = "Language",
+       [KEY_TITLE] = "Title",                  [KEY_SUBTITLE] = "Subtitle",
+       [KEY_ANGLE] = "Angle",                  [KEY_ZOOM] = "Zoom",
+       [KEY_MODE] = "Mode",                    [KEY_KEYBOARD] = "Keyboard",
+       [KEY_SCREEN] = "Screen",                [KEY_PC] = "PC",
+       [KEY_TV] = "TV",                        [KEY_TV2] = "TV2",
+       [KEY_VCR] = "VCR",                      [KEY_VCR2] = "VCR2",
+       [KEY_SAT] = "Sat",                      [KEY_SAT2] = "Sat2",
+       [KEY_CD] = "CD",                        [KEY_TAPE] = "Tape",
+       [KEY_RADIO] = "Radio",                  [KEY_TUNER] = "Tuner",
+       [KEY_PLAYER] = "Player",                [KEY_TEXT] = "Text",
+       [KEY_DVD] = "DVD",                      [KEY_AUX] = "Aux",
+       [KEY_MP3] = "MP3",                      [KEY_AUDIO] = "Audio",
+       [KEY_VIDEO] = "Video",                  [KEY_DIRECTORY] = "Directory",
+       [KEY_LIST] = "List",                    [KEY_MEMO] = "Memo",
+       [KEY_CALENDAR] = "Calendar",            [KEY_RED] = "Red",
+       [KEY_GREEN] = "Green",                  [KEY_YELLOW] = "Yellow",
+       [KEY_BLUE] = "Blue",                    [KEY_CHANNELUP] = "ChannelUp",
+       [KEY_CHANNELDOWN] = "ChannelDown",      [KEY_FIRST] = "First",
+       [KEY_LAST] = "Last",                    [KEY_AB] = "AB",
+       [KEY_NEXT] = "Next",                    [KEY_RESTART] = "Restart",
+       [KEY_SLOW] = "Slow",                    [KEY_SHUFFLE] = "Shuffle",
+       [KEY_BREAK] = "Break",                  [KEY_PREVIOUS] = "Previous",
+       [KEY_DIGITS] = "Digits",                [KEY_TEEN] = "TEEN",
+       [KEY_TWEN] = "TWEN",                    [KEY_DEL_EOL] = "DeleteEOL",
+       [KEY_DEL_EOS] = "DeleteEOS",            [KEY_INS_LINE] = "InsertLine",
+       [KEY_DEL_LINE] = "DeleteLine",
+       [KEY_SEND] = "Send",                    [KEY_REPLY] = "Reply",
+       [KEY_FORWARDMAIL] = "ForwardMail",      [KEY_SAVE] = "Save",
+       [KEY_DOCUMENTS] = "Documents",
+       [KEY_FN] = "Fn",                        [KEY_FN_ESC] = "Fn+ESC",
+       [KEY_FN_1] = "Fn+1",                    [KEY_FN_2] = "Fn+2",
+       [KEY_FN_B] = "Fn+B",                    [KEY_FN_D] = "Fn+D",
+       [KEY_FN_E] = "Fn+E",                    [KEY_FN_F] = "Fn+F",
+       [KEY_FN_S] = "Fn+S",
+       [KEY_FN_F1] = "Fn+F1",                  [KEY_FN_F2] = "Fn+F2",
+       [KEY_FN_F3] = "Fn+F3",                  [KEY_FN_F4] = "Fn+F4",
+       [KEY_FN_F5] = "Fn+F5",                  [KEY_FN_F6] = "Fn+F6",
+       [KEY_FN_F7] = "Fn+F7",                  [KEY_FN_F8] = "Fn+F8",
+       [KEY_FN_F9] = "Fn+F9",                  [KEY_FN_F10] = "Fn+F10",
+       [KEY_FN_F11] = "Fn+F11",                [KEY_FN_F12] = "Fn+F12",
+       [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
+       [KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
+       [KEY_KBDILLUMUP] = "KbdIlluminationUp",
+       [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
+};
+
+static char *relatives[REL_MAX + 1] = {
+       [REL_X] = "X",                  [REL_Y] = "Y",
+       [REL_Z] = "Z",                  [REL_RX] = "Rx",
+       [REL_RY] = "Ry",                [REL_RZ] = "Rz",
+       [REL_HWHEEL] = "HWheel",        [REL_DIAL] = "Dial",
+       [REL_WHEEL] = "Wheel",          [REL_MISC] = "Misc",
+};
+
+static char *absolutes[ABS_MAX + 1] = {
+       [ABS_X] = "X",                  [ABS_Y] = "Y",
+       [ABS_Z] = "Z",                  [ABS_RX] = "Rx",
+       [ABS_RY] = "Ry",                [ABS_RZ] = "Rz",
+       [ABS_THROTTLE] = "Throttle",    [ABS_RUDDER] = "Rudder",
+       [ABS_WHEEL] = "Wheel",          [ABS_GAS] = "Gas",
+       [ABS_BRAKE] = "Brake",          [ABS_HAT0X] = "Hat0X",
+       [ABS_HAT0Y] = "Hat0Y",          [ABS_HAT1X] = "Hat1X",
+       [ABS_HAT1Y] = "Hat1Y",          [ABS_HAT2X] = "Hat2X",
+       [ABS_HAT2Y] = "Hat2Y",          [ABS_HAT3X] = "Hat3X",
+       [ABS_HAT3Y] = "Hat 3Y",         [ABS_PRESSURE] = "Pressure",
+       [ABS_DISTANCE] = "Distance",    [ABS_TILT_X] = "XTilt",
+       [ABS_TILT_Y] = "YTilt",         [ABS_TOOL_WIDTH] = "Tool Width",
+       [ABS_VOLUME] = "Volume",        [ABS_MISC] = "Misc",
+};
+
+static char *misc[MSC_MAX + 1] = {
+       [MSC_SERIAL] = "Serial",        [MSC_PULSELED] = "Pulseled",
+       [MSC_GESTURE] = "Gesture",      [MSC_RAW] = "RawData"
+};
+
+static char *leds[LED_MAX + 1] = {
+       [LED_NUML] = "NumLock",         [LED_CAPSL] = "CapsLock",
+       [LED_SCROLLL] = "ScrollLock",   [LED_COMPOSE] = "Compose",
+       [LED_KANA] = "Kana",            [LED_SLEEP] = "Sleep",
+       [LED_SUSPEND] = "Suspend",      [LED_MUTE] = "Mute",
+       [LED_MISC] = "Misc",
+};
+
+static char *repeats[REP_MAX + 1] = {
+       [REP_DELAY] = "Delay",          [REP_PERIOD] = "Period"
+};
+
+static char *sounds[SND_MAX + 1] = {
+       [SND_CLICK] = "Click",          [SND_BELL] = "Bell",
+       [SND_TONE] = "Tone"
+};
+
+static char **names[EV_MAX + 1] = {
+       [EV_SYN] = syncs,                       [EV_KEY] = keys,
+       [EV_REL] = relatives,                   [EV_ABS] = absolutes,
+       [EV_MSC] = misc,                        [EV_LED] = leds,
+       [EV_SND] = sounds,                      [EV_REP] = repeats,
+};
+
+void hid_resolv_event(__u8 type, __u16 code) {
+
+       printk("%s.%s", events[type] ? events[type] : "?",
+               names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
+}
+EXPORT_SYMBOL_GPL(hid_resolv_event);
+
index c7a6833f68210ae90aa3c2c1902624304032b312..25d180a24fc42e1968de9b6b743c2ec76fd1c8c3 100644 (file)
@@ -31,9 +31,8 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 
-#undef DEBUG
-
 #include <linux/hid.h>
+#include <linux/hid-debug.h>
 
 static int hid_pb_fnmode = 1;
 module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644);
@@ -252,9 +251,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 
        field->hidinput = hidinput;
 
-#ifdef DEBUG
+#ifdef CONFIG_HID_DEBUG
        printk(KERN_DEBUG "Mapping: ");
-       resolv_usage(usage->hid);
+       hid_resolv_usage(usage->hid);
        printk(" ---> ");
 #endif
 
@@ -682,14 +681,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                        field->dpad = usage->code;
        }
 
-#ifdef DEBUG
-       resolv_event(usage->type, usage->code);
+       hid_resolv_event(usage->type, usage->code);
+#ifdef CONFIG_HID_DEBUG
        printk("\n");
 #endif
        return;
 
 ignore:
-#ifdef DEBUG
+#ifdef CONFIG_HID_DEBUG
        printk("IGNORED\n");
 #endif
        return;
@@ -804,6 +803,18 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int
 }
 EXPORT_SYMBOL_GPL(hidinput_find_field);
 
+static int hidinput_open(struct input_dev *dev)
+{
+       struct hid_device *hid = dev->private;
+       return hid->hid_open(hid);
+}
+
+static void hidinput_close(struct input_dev *dev)
+{
+       struct hid_device *hid = dev->private;
+       hid->hid_close(hid);
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -816,6 +827,7 @@ int hidinput_connect(struct hid_device *hid)
        struct hid_input *hidinput = NULL;
        struct input_dev *input_dev;
        int i, j, k;
+       int max_report_type = HID_OUTPUT_REPORT;
 
        INIT_LIST_HEAD(&hid->inputs);
 
@@ -828,7 +840,10 @@ int hidinput_connect(struct hid_device *hid)
        if (i == hid->maxcollection)
                return -1;
 
-       for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++)
+       if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
+               max_report_type = HID_INPUT_REPORT;
+
+       for (k = HID_INPUT_REPORT; k <= max_report_type; k++)
                list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
 
                        if (!report->maxfield)
@@ -846,8 +861,8 @@ int hidinput_connect(struct hid_device *hid)
 
                                input_dev->private = hid;
                                input_dev->event = hid->hidinput_input_event;
-                               input_dev->open = hid->hidinput_open;
-                               input_dev->close = hid->hidinput_close;
+                               input_dev->open = hidinput_open;
+                               input_dev->close = hidinput_close;
 
                                input_dev->name = hid->name;
                                input_dev->phys = hid->phys;
index af939796750dba07fd713f83dc3cf473ce52c43e..d2bb5a9a303fcb7d86f3a38deea2e33e7d8e9c2c 100644 (file)
@@ -360,8 +360,7 @@ static int netevent_callback(struct notifier_block *self, unsigned long event,
        if (event == NETEVENT_NEIGH_UPDATE) {
                struct neighbour *neigh = ctx;
 
-               if (neigh->dev->type == ARPHRD_INFINIBAND &&
-                   (neigh->nud_state & NUD_VALID)) {
+               if (neigh->nud_state & NUD_VALID) {
                        set_timeout(jiffies);
                }
        }
index 5ed141ebd1c86f1819819c3b15858c8d16907feb..13efd417034947dc12d812b8fd495cfc8802d210 100644 (file)
@@ -642,7 +642,8 @@ static void snoop_recv(struct ib_mad_qp_info *qp_info,
        spin_unlock_irqrestore(&qp_info->snoop_lock, flags);
 }
 
-static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
+static void build_smp_wc(struct ib_qp *qp,
+                        u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
                         struct ib_wc *wc)
 {
        memset(wc, 0, sizeof *wc);
@@ -652,7 +653,7 @@ static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num,
        wc->pkey_index = pkey_index;
        wc->byte_len = sizeof(struct ib_mad) + sizeof(struct ib_grh);
        wc->src_qp = IB_QP0;
-       wc->qp_num = IB_QP0;
+       wc->qp = qp;
        wc->slid = slid;
        wc->sl = 0;
        wc->dlid_path_bits = 0;
@@ -713,7 +714,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
                goto out;
        }
 
-       build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid),
+       build_smp_wc(mad_agent_priv->agent.qp,
+                    send_wr->wr_id, be16_to_cpu(smp->dr_slid),
                     send_wr->wr.ud.pkey_index,
                     send_wr->wr.ud.port_num, &mad_wc);
 
@@ -2355,7 +2357,8 @@ static void local_completions(struct work_struct *work)
                         * Defined behavior is to complete response
                         * before request
                         */
-                       build_smp_wc((unsigned long) local->mad_send_wr,
+                       build_smp_wc(recv_mad_agent->agent.qp,
+                                    (unsigned long) local->mad_send_wr,
                                     be16_to_cpu(IB_LID_PERMISSIVE),
                                     0, recv_mad_agent->agent.port_num, &wc);
 
index 743247ec065e152ce9d7237cfe136e24e7be41e4..df1efbc10882692b7de5a690d31cd8d79dec05a4 100644 (file)
@@ -933,7 +933,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
                resp->wc[i].vendor_err     = wc[i].vendor_err;
                resp->wc[i].byte_len       = wc[i].byte_len;
                resp->wc[i].imm_data       = (__u32 __force) wc[i].imm_data;
-               resp->wc[i].qp_num         = wc[i].qp_num;
+               resp->wc[i].qp_num         = wc[i].qp->qp_num;
                resp->wc[i].src_qp         = wc[i].src_qp;
                resp->wc[i].wc_flags       = wc[i].wc_flags;
                resp->wc[i].pkey_index     = wc[i].pkey_index;
index 05c9154d46f4a6125ce00d81cc2c4d3d02c0d357..5175c99ee586cc34000450cc68d1a56b0fe1773c 100644 (file)
@@ -153,7 +153,7 @@ static inline int c2_poll_one(struct c2_dev *c2dev,
 
        entry->status = c2_cqe_status_to_openib(c2_wr_get_result(ce));
        entry->wr_id = ce->hdr.context;
-       entry->qp_num = ce->handle;
+       entry->qp = &qp->ibqp;
        entry->wc_flags = 0;
        entry->slid = 0;
        entry->sl = 0;
index 1c722032319cae74649ca4ccd339f7d1c33aad0f..cf95ee474b0f6a1105551ce69f342168d5c2034e 100644 (file)
@@ -119,13 +119,14 @@ struct ehca_qp {
        struct ipz_qp_handle ipz_qp_handle;
        struct ehca_pfqp pf;
        struct ib_qp_init_attr init_attr;
-       u64 uspace_squeue;
-       u64 uspace_rqueue;
-       u64 uspace_fwh;
        struct ehca_cq *send_cq;
        struct ehca_cq *recv_cq;
        unsigned int sqerr_purgeflag;
        struct hlist_node list_entries;
+       /* mmap counter for resources mapped into user space */
+       u32 mm_count_squeue;
+       u32 mm_count_rqueue;
+       u32 mm_count_galpa;
 };
 
 /* must be power of 2 */
@@ -142,13 +143,14 @@ struct ehca_cq {
        struct ipz_cq_handle ipz_cq_handle;
        struct ehca_pfcq pf;
        spinlock_t cb_lock;
-       u64 uspace_queue;
-       u64 uspace_fwh;
        struct hlist_head qp_hashtab[QP_HASHTAB_LEN];
        struct list_head entry;
        u32 nr_callbacks;
        spinlock_t task_lock;
        u32 ownpid;
+       /* mmap counter for resources mapped into user space */
+       u32 mm_count_queue;
+       u32 mm_count_galpa;
 };
 
 enum ehca_mr_flag {
@@ -248,20 +250,6 @@ struct ehca_ucontext {
        struct ib_ucontext ib_ucontext;
 };
 
-struct ehca_module *ehca_module_new(void);
-
-int ehca_module_delete(struct ehca_module *me);
-
-int ehca_eq_ctor(struct ehca_eq *eq);
-
-int ehca_eq_dtor(struct ehca_eq *eq);
-
-struct ehca_shca *ehca_shca_new(void);
-
-int ehca_shca_delete(struct ehca_shca *me);
-
-struct ehca_sport *ehca_sport_new(struct ehca_shca *anchor);
-
 int ehca_init_pd_cache(void);
 void ehca_cleanup_pd_cache(void);
 int ehca_init_cq_cache(void);
@@ -283,7 +271,6 @@ extern int ehca_port_act_time;
 extern int ehca_use_hp_mr;
 
 struct ipzu_queue_resp {
-       u64 queue;        /* points to first queue entry */
        u32 qe_size;      /* queue entry size */
        u32 act_nr_of_sg;
        u32 queue_length; /* queue length allocated in bytes */
@@ -296,7 +283,6 @@ struct ehca_create_cq_resp {
        u32 cq_number;
        u32 token;
        struct ipzu_queue_resp ipz_queue;
-       struct h_galpas galpas;
 };
 
 struct ehca_create_qp_resp {
@@ -309,7 +295,6 @@ struct ehca_create_qp_resp {
        u32 dummy; /* padding for 8 byte alignment */
        struct ipzu_queue_resp ipz_squeue;
        struct ipzu_queue_resp ipz_rqueue;
-       struct h_galpas galpas;
 };
 
 struct ehca_alloc_cq_parms {
index 6074c897f51c81a1a8da9b478eb59091ec851c96..9291a86ca0537f279868ded87046d69a6ad18b5f 100644 (file)
@@ -267,7 +267,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
        if (context) {
                struct ipz_queue *ipz_queue = &my_cq->ipz_queue;
                struct ehca_create_cq_resp resp;
-               struct vm_area_struct *vma;
                memset(&resp, 0, sizeof(resp));
                resp.cq_number = my_cq->cq_number;
                resp.token = my_cq->token;
@@ -276,40 +275,14 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe,
                resp.ipz_queue.queue_length = ipz_queue->queue_length;
                resp.ipz_queue.pagesize = ipz_queue->pagesize;
                resp.ipz_queue.toggle_state = ipz_queue->toggle_state;
-               ret = ehca_mmap_nopage(((u64)(my_cq->token) << 32) | 0x12000000,
-                                      ipz_queue->queue_length,
-                                      (void**)&resp.ipz_queue.queue,
-                                      &vma);
-               if (ret) {
-                       ehca_err(device, "Could not mmap queue pages");
-                       cq = ERR_PTR(ret);
-                       goto create_cq_exit4;
-               }
-               my_cq->uspace_queue = resp.ipz_queue.queue;
-               resp.galpas = my_cq->galpas;
-               ret = ehca_mmap_register(my_cq->galpas.user.fw_handle,
-                                        (void**)&resp.galpas.kernel.fw_handle,
-                                        &vma);
-               if (ret) {
-                       ehca_err(device, "Could not mmap fw_handle");
-                       cq = ERR_PTR(ret);
-                       goto create_cq_exit5;
-               }
-               my_cq->uspace_fwh = (u64)resp.galpas.kernel.fw_handle;
                if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
                        ehca_err(device, "Copy to udata failed.");
-                       goto create_cq_exit6;
+                       goto create_cq_exit4;
                }
        }
 
        return cq;
 
-create_cq_exit6:
-       ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE);
-
-create_cq_exit5:
-       ehca_munmap(my_cq->uspace_queue, my_cq->ipz_queue.queue_length);
-
 create_cq_exit4:
        ipz_queue_dtor(&my_cq->ipz_queue);
 
@@ -333,7 +306,6 @@ create_cq_exit1:
 int ehca_destroy_cq(struct ib_cq *cq)
 {
        u64 h_ret;
-       int ret;
        struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
        int cq_num = my_cq->cq_number;
        struct ib_device *device = cq->device;
@@ -343,6 +315,20 @@ int ehca_destroy_cq(struct ib_cq *cq)
        u32 cur_pid = current->tgid;
        unsigned long flags;
 
+       if (cq->uobject) {
+               if (my_cq->mm_count_galpa || my_cq->mm_count_queue) {
+                       ehca_err(device, "Resources still referenced in "
+                                "user space cq_num=%x", my_cq->cq_number);
+                       return -EINVAL;
+               }
+               if (my_cq->ownpid != cur_pid) {
+                       ehca_err(device, "Invalid caller pid=%x ownpid=%x "
+                                "cq_num=%x",
+                                cur_pid, my_cq->ownpid, my_cq->cq_number);
+                       return -EINVAL;
+               }
+       }
+
        spin_lock_irqsave(&ehca_cq_idr_lock, flags);
        while (my_cq->nr_callbacks) {
                spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
@@ -353,25 +339,6 @@ int ehca_destroy_cq(struct ib_cq *cq)
        idr_remove(&ehca_cq_idr, my_cq->token);
        spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
 
-       if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) {
-               ehca_err(device, "Invalid caller pid=%x ownpid=%x",
-                        cur_pid, my_cq->ownpid);
-               return -EINVAL;
-       }
-
-       /* un-mmap if vma alloc */
-       if (my_cq->uspace_queue ) {
-               ret = ehca_munmap(my_cq->uspace_queue,
-                                 my_cq->ipz_queue.queue_length);
-               if (ret)
-                       ehca_err(device, "Could not munmap queue ehca_cq=%p "
-                                "cq_num=%x", my_cq, cq_num);
-               ret = ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE);
-               if (ret)
-                       ehca_err(device, "Could not munmap fwh ehca_cq=%p "
-                                "cq_num=%x", my_cq, cq_num);
-       }
-
        h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0);
        if (h_ret == H_R_STATE) {
                /* cq in err: read err data and destroy it forcibly */
@@ -400,7 +367,7 @@ int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata)
        struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq);
        u32 cur_pid = current->tgid;
 
-       if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) {
+       if (cq->uobject && my_cq->ownpid != cur_pid) {
                ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x",
                         cur_pid, my_cq->ownpid);
                return -EINVAL;
index cd7789f0d08ecbb99a1a9da168b58d4d78182fab..95fd59fb4528b2db54576992c9538ba611346e3f 100644 (file)
@@ -171,14 +171,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
 
 void ehca_poll_eqs(unsigned long data);
 
-int ehca_mmap_nopage(u64 foffset,u64 length,void **mapped,
-                    struct vm_area_struct **vma);
-
-int ehca_mmap_register(u64 physical,void **mapped,
-                      struct vm_area_struct **vma);
-
-int ehca_munmap(unsigned long addr, size_t len);
-
 #ifdef CONFIG_PPC_64K_PAGES
 void *ehca_alloc_fw_ctrlblock(gfp_t flags);
 void ehca_free_fw_ctrlblock(void *ptr);
index 6574fbbaead5e8faf0f65d7e98ca3c75c4bede05..1155bcf48212ef33da22d188a4530d7545e92661 100644 (file)
@@ -52,7 +52,7 @@
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
 MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0019");
+MODULE_VERSION("SVNEHCA_0020");
 
 int ehca_open_aqp1     = 0;
 int ehca_debug_level   = 0;
@@ -288,7 +288,7 @@ int ehca_init_device(struct ehca_shca *shca)
        strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX);
        shca->ib_device.owner               = THIS_MODULE;
 
-       shca->ib_device.uverbs_abi_ver      = 5;
+       shca->ib_device.uverbs_abi_ver      = 6;
        shca->ib_device.uverbs_cmd_mask     =
                (1ull << IB_USER_VERBS_CMD_GET_CONTEXT)         |
                (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE)        |
@@ -790,7 +790,7 @@ int __init ehca_module_init(void)
        int ret;
 
        printk(KERN_INFO "eHCA Infiniband Device Driver "
-                        "(Rel.: SVNEHCA_0019)\n");
+                        "(Rel.: SVNEHCA_0020)\n");
        idr_init(&ehca_qp_idr);
        idr_init(&ehca_cq_idr);
        spin_lock_init(&ehca_qp_idr_lock);
index 34b85556d01e0d55b8524f62ac1f65aef2be63e5..95efef921f1d9fed9543ca5b0f889af9c4f74862 100644 (file)
@@ -637,7 +637,6 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
                struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue;
                struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue;
                struct ehca_create_qp_resp resp;
-               struct vm_area_struct * vma;
                memset(&resp, 0, sizeof(resp));
 
                resp.qp_num = my_qp->real_qp_num;
@@ -651,59 +650,21 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd,
                resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length;
                resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize;
                resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state;
-               ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x22000000,
-                                      ipz_rqueue->queue_length,
-                                      (void**)&resp.ipz_rqueue.queue,
-                                      &vma);
-               if (ret) {
-                       ehca_err(pd->device, "Could not mmap rqueue pages");
-                       goto create_qp_exit3;
-               }
-               my_qp->uspace_rqueue = resp.ipz_rqueue.queue;
                /* squeue properties */
                resp.ipz_squeue.qe_size = ipz_squeue->qe_size;
                resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg;
                resp.ipz_squeue.queue_length = ipz_squeue->queue_length;
                resp.ipz_squeue.pagesize = ipz_squeue->pagesize;
                resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state;
-               ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x23000000,
-                                      ipz_squeue->queue_length,
-                                      (void**)&resp.ipz_squeue.queue,
-                                      &vma);
-               if (ret) {
-                       ehca_err(pd->device, "Could not mmap squeue pages");
-                       goto create_qp_exit4;
-               }
-               my_qp->uspace_squeue = resp.ipz_squeue.queue;
-               /* fw_handle */
-               resp.galpas = my_qp->galpas;
-               ret = ehca_mmap_register(my_qp->galpas.user.fw_handle,
-                                        (void**)&resp.galpas.kernel.fw_handle,
-                                        &vma);
-               if (ret) {
-                       ehca_err(pd->device, "Could not mmap fw_handle");
-                       goto create_qp_exit5;
-               }
-               my_qp->uspace_fwh = (u64)resp.galpas.kernel.fw_handle;
-
                if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
                        ehca_err(pd->device, "Copy to udata failed");
                        ret = -EINVAL;
-                       goto create_qp_exit6;
+                       goto create_qp_exit3;
                }
        }
 
        return &my_qp->ib_qp;
 
-create_qp_exit6:
-       ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE);
-
-create_qp_exit5:
-       ehca_munmap(my_qp->uspace_squeue, my_qp->ipz_squeue.queue_length);
-
-create_qp_exit4:
-       ehca_munmap(my_qp->uspace_rqueue, my_qp->ipz_rqueue.queue_length);
-
 create_qp_exit3:
        ipz_queue_dtor(&my_qp->ipz_rqueue);
        ipz_queue_dtor(&my_qp->ipz_squeue);
@@ -931,7 +892,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
             my_qp->qp_type == IB_QPT_SMI) &&
            statetrans == IB_QPST_SQE2RTS) {
                /* mark next free wqe if kernel */
-               if (my_qp->uspace_squeue == 0) {
+               if (!ibqp->uobject) {
                        struct ehca_wqe *wqe;
                        /* lock send queue */
                        spin_lock_irqsave(&my_qp->spinlock_s, spl_flags);
@@ -1417,11 +1378,18 @@ int ehca_destroy_qp(struct ib_qp *ibqp)
        enum ib_qp_type qp_type;
        unsigned long flags;
 
-       if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context &&
-           my_pd->ownpid != cur_pid) {
-               ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x",
-                        cur_pid, my_pd->ownpid);
-               return -EINVAL;
+       if (ibqp->uobject) {
+               if (my_qp->mm_count_galpa ||
+                   my_qp->mm_count_rqueue || my_qp->mm_count_squeue) {
+                       ehca_err(ibqp->device, "Resources still referenced in "
+                                "user space qp_num=%x", ibqp->qp_num);
+                       return -EINVAL;
+               }
+               if (my_pd->ownpid != cur_pid) {
+                       ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x",
+                                cur_pid, my_pd->ownpid);
+                       return -EINVAL;
+               }
        }
 
        if (my_qp->send_cq) {
@@ -1439,24 +1407,6 @@ int ehca_destroy_qp(struct ib_qp *ibqp)
        idr_remove(&ehca_qp_idr, my_qp->token);
        spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
 
-       /* un-mmap if vma alloc */
-       if (my_qp->uspace_rqueue) {
-               ret = ehca_munmap(my_qp->uspace_rqueue,
-                                 my_qp->ipz_rqueue.queue_length);
-               if (ret)
-                       ehca_err(ibqp->device, "Could not munmap rqueue "
-                                "qp_num=%x", qp_num);
-               ret = ehca_munmap(my_qp->uspace_squeue,
-                                 my_qp->ipz_squeue.queue_length);
-               if (ret)
-                       ehca_err(ibqp->device, "Could not munmap squeue "
-                                "qp_num=%x", qp_num);
-               ret = ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE);
-               if (ret)
-                       ehca_err(ibqp->device, "Could not munmap fwh qp_num=%x",
-                                qp_num);
-       }
-
        h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp);
        if (h_ret != H_SUCCESS) {
                ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx "
index b46bda1bf85d7d106aaf1249414c3e50e56e851d..08d3f892d9f35695b7f83b17cfbd44b680d8d00f 100644 (file)
@@ -579,7 +579,7 @@ poll_cq_one_read_cqe:
        } else
                wc->status = IB_WC_SUCCESS;
 
-       wc->qp_num = cqe->local_qp_number;
+       wc->qp = NULL;
        wc->byte_len = cqe->nr_bytes_transferred;
        wc->pkey_index = cqe->pkey_index;
        wc->slid = cqe->rlid;
index e08764e4aef280985f7dd3da545d32205b8e2ec9..73db920b6945e7b255f3ac2ac996ab87b42aa2de 100644 (file)
@@ -68,105 +68,183 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context)
        return 0;
 }
 
-struct page *ehca_nopage(struct vm_area_struct *vma,
-                        unsigned long address, int *type)
+static void ehca_mm_open(struct vm_area_struct *vma)
 {
-       struct page *mypage = NULL;
-       u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT;
-       u32 idr_handle = fileoffset >> 32;
-       u32 q_type = (fileoffset >> 28) & 0xF;    /* CQ, QP,...        */
-       u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
-       u32 cur_pid = current->tgid;
-       unsigned long flags;
-       struct ehca_cq *cq;
-       struct ehca_qp *qp;
-       struct ehca_pd *pd;
-       u64 offset;
-       void *vaddr;
+       u32 *count = (u32*)vma->vm_private_data;
+       if (!count) {
+               ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
+                            vma->vm_start, vma->vm_end);
+               return;
+       }
+       (*count)++;
+       if (!(*count))
+               ehca_gen_err("Use count overflow vm_start=%lx vm_end=%lx",
+                            vma->vm_start, vma->vm_end);
+       ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
+                    vma->vm_start, vma->vm_end, *count);
+}
 
-       switch (q_type) {
-       case 1: /* CQ */
-               spin_lock_irqsave(&ehca_cq_idr_lock, flags);
-               cq = idr_find(&ehca_cq_idr, idr_handle);
-               spin_unlock_irqrestore(&ehca_cq_idr_lock, flags);
+static void ehca_mm_close(struct vm_area_struct *vma)
+{
+       u32 *count = (u32*)vma->vm_private_data;
+       if (!count) {
+               ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx",
+                            vma->vm_start, vma->vm_end);
+               return;
+       }
+       (*count)--;
+       ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x",
+                    vma->vm_start, vma->vm_end, *count);
+}
 
-               /* make sure this mmap really belongs to the authorized user */
-               if (!cq) {
-                       ehca_gen_err("cq is NULL ret=NOPAGE_SIGBUS");
-                       return NOPAGE_SIGBUS;
+static struct vm_operations_struct vm_ops = {
+       .open = ehca_mm_open,
+       .close = ehca_mm_close,
+};
+
+static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas,
+                       u32 *mm_count)
+{
+       int ret;
+       u64 vsize, physical;
+
+       vsize = vma->vm_end - vma->vm_start;
+       if (vsize != EHCA_PAGESIZE) {
+               ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start);
+               return -EINVAL;
+       }
+
+       physical = galpas->user.fw_handle;
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       ehca_gen_dbg("vsize=%lx physical=%lx", vsize, physical);
+       /* VM_IO | VM_RESERVED are set by remap_pfn_range() */
+       ret = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT,
+                             vsize, vma->vm_page_prot);
+       if (unlikely(ret)) {
+               ehca_gen_err("remap_pfn_range() failed ret=%x", ret);
+               return -ENOMEM;
+       }
+
+       vma->vm_private_data = mm_count;
+       (*mm_count)++;
+       vma->vm_ops = &vm_ops;
+
+       return 0;
+}
+
+static int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue,
+                          u32 *mm_count)
+{
+       int ret;
+       u64 start, ofs;
+       struct page *page;
+
+       vma->vm_flags |= VM_RESERVED;
+       start = vma->vm_start;
+       for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) {
+               u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs);
+               page = virt_to_page(virt_addr);
+               ret = vm_insert_page(vma, start, page);
+               if (unlikely(ret)) {
+                       ehca_gen_err("vm_insert_page() failed rc=%x", ret);
+                       return ret;
                }
+               start +=  PAGE_SIZE;
+       }
+       vma->vm_private_data = mm_count;
+       (*mm_count)++;
+       vma->vm_ops = &vm_ops;
 
-               if (cq->ownpid != cur_pid) {
+       return 0;
+}
+
+static int ehca_mmap_cq(struct vm_area_struct *vma, struct ehca_cq *cq,
+                       u32 rsrc_type)
+{
+       int ret;
+
+       switch (rsrc_type) {
+       case 1: /* galpa fw handle */
+               ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number);
+               ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa);
+               if (unlikely(ret)) {
                        ehca_err(cq->ib_cq.device,
-                                "Invalid caller pid=%x ownpid=%x",
-                                cur_pid, cq->ownpid);
-                       return NOPAGE_SIGBUS;
+                                "ehca_mmap_fw() failed rc=%x cq_num=%x",
+                                ret, cq->cq_number);
+                       return ret;
                }
+               break;
 
-               if (rsrc_type == 2) {
-                       ehca_dbg(cq->ib_cq.device, "cq=%p cq queuearea", cq);
-                       offset = address - vma->vm_start;
-                       vaddr = ipz_qeit_calc(&cq->ipz_queue, offset);
-                       ehca_dbg(cq->ib_cq.device, "offset=%lx vaddr=%p",
-                                offset, vaddr);
-                       mypage = virt_to_page(vaddr);
+       case 2: /* cq queue_addr */
+               ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number);
+               ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue);
+               if (unlikely(ret)) {
+                       ehca_err(cq->ib_cq.device,
+                                "ehca_mmap_queue() failed rc=%x cq_num=%x",
+                                ret, cq->cq_number);
+                       return ret;
                }
                break;
 
-       case 2: /* QP */
-               spin_lock_irqsave(&ehca_qp_idr_lock, flags);
-               qp = idr_find(&ehca_qp_idr, idr_handle);
-               spin_unlock_irqrestore(&ehca_qp_idr_lock, flags);
+       default:
+               ehca_err(cq->ib_cq.device, "bad resource type=%x cq_num=%x",
+                        rsrc_type, cq->cq_number);
+               return -EINVAL;
+       }
 
-               /* make sure this mmap really belongs to the authorized user */
-               if (!qp) {
-                       ehca_gen_err("qp is NULL ret=NOPAGE_SIGBUS");
-                       return NOPAGE_SIGBUS;
+       return 0;
+}
+
+static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp,
+                       u32 rsrc_type)
+{
+       int ret;
+
+       switch (rsrc_type) {
+       case 1: /* galpa fw handle */
+               ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num);
+               ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa);
+               if (unlikely(ret)) {
+                       ehca_err(qp->ib_qp.device,
+                                "remap_pfn_range() failed ret=%x qp_num=%x",
+                                ret, qp->ib_qp.qp_num);
+                       return -ENOMEM;
                }
+               break;
 
-               pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd);
-               if (pd->ownpid != cur_pid) {
+       case 2: /* qp rqueue_addr */
+               ehca_dbg(qp->ib_qp.device, "qp_num=%x rqueue",
+                        qp->ib_qp.qp_num);
+               ret = ehca_mmap_queue(vma, &qp->ipz_rqueue, &qp->mm_count_rqueue);
+               if (unlikely(ret)) {
                        ehca_err(qp->ib_qp.device,
-                                "Invalid caller pid=%x ownpid=%x",
-                                cur_pid, pd->ownpid);
-                       return NOPAGE_SIGBUS;
+                                "ehca_mmap_queue(rq) failed rc=%x qp_num=%x",
+                                ret, qp->ib_qp.qp_num);
+                       return ret;
                }
+               break;
 
-               if (rsrc_type == 2) {   /* rqueue */
-                       ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueuearea", qp);
-                       offset = address - vma->vm_start;
-                       vaddr = ipz_qeit_calc(&qp->ipz_rqueue, offset);
-                       ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p",
-                                offset, vaddr);
-                       mypage = virt_to_page(vaddr);
-               } else if (rsrc_type == 3) {    /* squeue */
-                       ehca_dbg(qp->ib_qp.device, "qp=%p qp squeuearea", qp);
-                       offset = address - vma->vm_start;
-                       vaddr = ipz_qeit_calc(&qp->ipz_squeue, offset);
-                       ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p",
-                                offset, vaddr);
-                       mypage = virt_to_page(vaddr);
+       case 3: /* qp squeue_addr */
+               ehca_dbg(qp->ib_qp.device, "qp_num=%x squeue",
+                        qp->ib_qp.qp_num);
+               ret = ehca_mmap_queue(vma, &qp->ipz_squeue, &qp->mm_count_squeue);
+               if (unlikely(ret)) {
+                       ehca_err(qp->ib_qp.device,
+                                "ehca_mmap_queue(sq) failed rc=%x qp_num=%x",
+                                ret, qp->ib_qp.qp_num);
+                       return ret;
                }
                break;
 
        default:
-               ehca_gen_err("bad queue type %x", q_type);
-               return NOPAGE_SIGBUS;
-       }
-
-       if (!mypage) {
-               ehca_gen_err("Invalid page adr==NULL ret=NOPAGE_SIGBUS");
-               return NOPAGE_SIGBUS;
+               ehca_err(qp->ib_qp.device, "bad resource type=%x qp=num=%x",
+                        rsrc_type, qp->ib_qp.qp_num);
+               return -EINVAL;
        }
-       get_page(mypage);
 
-       return mypage;
+       return 0;
 }
 
-static struct vm_operations_struct ehcau_vm_ops = {
-       .nopage = ehca_nopage,
-};
-
 int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 {
        u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT;
@@ -175,7 +253,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
        u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */
        u32 cur_pid = current->tgid;
        u32 ret;
-       u64 vsize, physical;
        unsigned long flags;
        struct ehca_cq *cq;
        struct ehca_qp *qp;
@@ -201,44 +278,12 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
                if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context)
                        return -EINVAL;
 
-               switch (rsrc_type) {
-               case 1: /* galpa fw handle */
-                       ehca_dbg(cq->ib_cq.device, "cq=%p cq triggerarea", cq);
-                       vma->vm_flags |= VM_RESERVED;
-                       vsize = vma->vm_end - vma->vm_start;
-                       if (vsize != EHCA_PAGESIZE) {
-                               ehca_err(cq->ib_cq.device, "invalid vsize=%lx",
-                                        vma->vm_end - vma->vm_start);
-                               return -EINVAL;
-                       }
-
-                       physical = cq->galpas.user.fw_handle;
-                       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-                       vma->vm_flags |= VM_IO | VM_RESERVED;
-
-                       ehca_dbg(cq->ib_cq.device,
-                                "vsize=%lx physical=%lx", vsize, physical);
-                       ret = remap_pfn_range(vma, vma->vm_start,
-                                             physical >> PAGE_SHIFT, vsize,
-                                             vma->vm_page_prot);
-                       if (ret) {
-                               ehca_err(cq->ib_cq.device,
-                                        "remap_pfn_range() failed ret=%x",
-                                        ret);
-                               return -ENOMEM;
-                       }
-                       break;
-
-               case 2: /* cq queue_addr */
-                       ehca_dbg(cq->ib_cq.device, "cq=%p cq q_addr", cq);
-                       vma->vm_flags |= VM_RESERVED;
-                       vma->vm_ops = &ehcau_vm_ops;
-                       break;
-
-               default:
-                       ehca_err(cq->ib_cq.device, "bad resource type %x",
-                                rsrc_type);
-                       return -EINVAL;
+               ret = ehca_mmap_cq(vma, cq, rsrc_type);
+               if (unlikely(ret)) {
+                       ehca_err(cq->ib_cq.device,
+                                "ehca_mmap_cq() failed rc=%x cq_num=%x",
+                                ret, cq->cq_number);
+                       return ret;
                }
                break;
 
@@ -262,50 +307,12 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
                if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context)
                        return -EINVAL;
 
-               switch (rsrc_type) {
-               case 1: /* galpa fw handle */
-                       ehca_dbg(qp->ib_qp.device, "qp=%p qp triggerarea", qp);
-                       vma->vm_flags |= VM_RESERVED;
-                       vsize = vma->vm_end - vma->vm_start;
-                       if (vsize != EHCA_PAGESIZE) {
-                               ehca_err(qp->ib_qp.device, "invalid vsize=%lx",
-                                        vma->vm_end - vma->vm_start);
-                               return -EINVAL;
-                       }
-
-                       physical = qp->galpas.user.fw_handle;
-                       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-                       vma->vm_flags |= VM_IO | VM_RESERVED;
-
-                       ehca_dbg(qp->ib_qp.device, "vsize=%lx physical=%lx",
-                                vsize, physical);
-                       ret = remap_pfn_range(vma, vma->vm_start,
-                                             physical >> PAGE_SHIFT, vsize,
-                                             vma->vm_page_prot);
-                       if (ret) {
-                               ehca_err(qp->ib_qp.device,
-                                        "remap_pfn_range() failed ret=%x",
-                                        ret);
-                               return -ENOMEM;
-                       }
-                       break;
-
-               case 2: /* qp rqueue_addr */
-                       ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueue_addr", qp);
-                       vma->vm_flags |= VM_RESERVED;
-                       vma->vm_ops = &ehcau_vm_ops;
-                       break;
-
-               case 3: /* qp squeue_addr */
-                       ehca_dbg(qp->ib_qp.device, "qp=%p qp squeue_addr", qp);
-                       vma->vm_flags |= VM_RESERVED;
-                       vma->vm_ops = &ehcau_vm_ops;
-                       break;
-
-               default:
-                       ehca_err(qp->ib_qp.device, "bad resource type %x",
-                                rsrc_type);
-                       return -EINVAL;
+               ret = ehca_mmap_qp(vma, qp, rsrc_type);
+               if (unlikely(ret)) {
+                       ehca_err(qp->ib_qp.device,
+                                "ehca_mmap_qp() failed rc=%x qp_num=%x",
+                                ret, qp->ib_qp.qp_num);
+                       return ret;
                }
                break;
 
@@ -316,77 +323,3 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 
        return 0;
 }
-
-int ehca_mmap_nopage(u64 foffset, u64 length, void **mapped,
-                    struct vm_area_struct **vma)
-{
-       down_write(&current->mm->mmap_sem);
-       *mapped = (void*)do_mmap(NULL,0, length, PROT_WRITE,
-                                MAP_SHARED | MAP_ANONYMOUS,
-                                foffset);
-       up_write(&current->mm->mmap_sem);
-       if (!(*mapped)) {
-               ehca_gen_err("couldn't mmap foffset=%lx length=%lx",
-                            foffset, length);
-               return -EINVAL;
-       }
-
-       *vma = find_vma(current->mm, (u64)*mapped);
-       if (!(*vma)) {
-               down_write(&current->mm->mmap_sem);
-               do_munmap(current->mm, 0, length);
-               up_write(&current->mm->mmap_sem);
-               ehca_gen_err("couldn't find vma queue=%p", *mapped);
-               return -EINVAL;
-       }
-       (*vma)->vm_flags |= VM_RESERVED;
-       (*vma)->vm_ops = &ehcau_vm_ops;
-
-       return 0;
-}
-
-int ehca_mmap_register(u64 physical, void **mapped,
-                      struct vm_area_struct **vma)
-{
-       int ret;
-       unsigned long vsize;
-       /* ehca hw supports only 4k page */
-       ret = ehca_mmap_nopage(0, EHCA_PAGESIZE, mapped, vma);
-       if (ret) {
-               ehca_gen_err("could'nt mmap physical=%lx", physical);
-               return ret;
-       }
-
-       (*vma)->vm_flags |= VM_RESERVED;
-       vsize = (*vma)->vm_end - (*vma)->vm_start;
-       if (vsize != EHCA_PAGESIZE) {
-               ehca_gen_err("invalid vsize=%lx",
-                            (*vma)->vm_end - (*vma)->vm_start);
-               return -EINVAL;
-       }
-
-       (*vma)->vm_page_prot = pgprot_noncached((*vma)->vm_page_prot);
-       (*vma)->vm_flags |= VM_IO | VM_RESERVED;
-
-       ret = remap_pfn_range((*vma), (*vma)->vm_start,
-                             physical >> PAGE_SHIFT, vsize,
-                             (*vma)->vm_page_prot);
-       if (ret) {
-               ehca_gen_err("remap_pfn_range() failed ret=%x", ret);
-               return -ENOMEM;
-       }
-
-       return 0;
-
-}
-
-int ehca_munmap(unsigned long addr, size_t len) {
-       int ret = 0;
-       struct mm_struct *mm = current->mm;
-       if (mm) {
-               down_write(&mm->mmap_sem);
-               ret = do_munmap(mm, addr, len);
-               up_write(&mm->mmap_sem);
-       }
-       return ret;
-}
index 46c1c89bf6ae2748dd5779ddca0c24a44e271af6..64f07b19349fadc8ca88a2c27eac01b89fa13498 100644 (file)
@@ -379,7 +379,7 @@ void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
        wc.vendor_err = 0;
        wc.byte_len = 0;
        wc.imm_data = 0;
-       wc.qp_num = qp->ibqp.qp_num;
+       wc.qp = &qp->ibqp;
        wc.src_qp = 0;
        wc.wc_flags = 0;
        wc.pkey_index = 0;
index ce6038743c5c258bd7b06bbaf62d77a7d6ab4bbe..5ff20cb04494c5eaf63da3725ca135c544790f40 100644 (file)
@@ -702,7 +702,7 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc)
                wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
                wc->vendor_err = 0;
                wc->byte_len = 0;
-               wc->qp_num = qp->ibqp.qp_num;
+               wc->qp = &qp->ibqp;
                wc->src_qp = qp->remote_qpn;
                wc->pkey_index = 0;
                wc->slid = qp->remote_ah_attr.dlid;
@@ -836,7 +836,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
                        wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
                        wc.vendor_err = 0;
                        wc.byte_len = wqe->length;
-                       wc.qp_num = qp->ibqp.qp_num;
+                       wc.qp = &qp->ibqp;
                        wc.src_qp = qp->remote_qpn;
                        wc.pkey_index = 0;
                        wc.slid = qp->remote_ah_attr.dlid;
@@ -951,7 +951,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode)
                        wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
                        wc.vendor_err = 0;
                        wc.byte_len = 0;
-                       wc.qp_num = qp->ibqp.qp_num;
+                       wc.qp = &qp->ibqp;
                        wc.src_qp = qp->remote_qpn;
                        wc.pkey_index = 0;
                        wc.slid = qp->remote_ah_attr.dlid;
@@ -1511,7 +1511,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                wc.status = IB_WC_SUCCESS;
                wc.opcode = IB_WC_RECV;
                wc.vendor_err = 0;
-               wc.qp_num = qp->ibqp.qp_num;
+               wc.qp = &qp->ibqp;
                wc.src_qp = qp->remote_qpn;
                wc.pkey_index = 0;
                wc.slid = qp->remote_ah_attr.dlid;
index f7530512045d0f0e7584424e020e1e5169909a29..e86cb171872e2c9ecc3d0c99e74d3f3a0ce3af93 100644 (file)
@@ -137,7 +137,7 @@ bad_lkey:
        wc.vendor_err = 0;
        wc.byte_len = 0;
        wc.imm_data = 0;
-       wc.qp_num = qp->ibqp.qp_num;
+       wc.qp = &qp->ibqp;
        wc.src_qp = 0;
        wc.wc_flags = 0;
        wc.pkey_index = 0;
@@ -336,7 +336,7 @@ again:
                        wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
                        wc.vendor_err = 0;
                        wc.byte_len = 0;
-                       wc.qp_num = sqp->ibqp.qp_num;
+                       wc.qp = &sqp->ibqp;
                        wc.src_qp = sqp->remote_qpn;
                        wc.pkey_index = 0;
                        wc.slid = sqp->remote_ah_attr.dlid;
@@ -426,7 +426,7 @@ again:
        wc.status = IB_WC_SUCCESS;
        wc.vendor_err = 0;
        wc.byte_len = wqe->length;
-       wc.qp_num = qp->ibqp.qp_num;
+       wc.qp = &qp->ibqp;
        wc.src_qp = qp->remote_qpn;
        /* XXX do we know which pkey matched? Only needed for GSI. */
        wc.pkey_index = 0;
@@ -447,7 +447,7 @@ send_comp:
                wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
                wc.vendor_err = 0;
                wc.byte_len = wqe->length;
-               wc.qp_num = sqp->ibqp.qp_num;
+               wc.qp = &sqp->ibqp;
                wc.src_qp = 0;
                wc.pkey_index = 0;
                wc.slid = 0;
index e636cfd67a821f74349c48d1f64f80d3bc9e94ab..325d6634ff53f81c5ebd354102c975a23d30d4f2 100644 (file)
@@ -49,7 +49,7 @@ static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe,
                wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
                wc->vendor_err = 0;
                wc->byte_len = wqe->length;
-               wc->qp_num = qp->ibqp.qp_num;
+               wc->qp = &qp->ibqp;
                wc->src_qp = qp->remote_qpn;
                wc->pkey_index = 0;
                wc->slid = qp->remote_ah_attr.dlid;
@@ -411,7 +411,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
                wc.status = IB_WC_SUCCESS;
                wc.opcode = IB_WC_RECV;
                wc.vendor_err = 0;
-               wc.qp_num = qp->ibqp.qp_num;
+               wc.qp = &qp->ibqp;
                wc.src_qp = qp->remote_qpn;
                wc.pkey_index = 0;
                wc.slid = qp->remote_ah_attr.dlid;
index 49f1102af8b36635427459aa52faeb76b2e2afd0..9a3e54664ee49f1aa9ba0dc0e9a1158e5a157650 100644 (file)
@@ -66,7 +66,7 @@ bad_lkey:
        wc.vendor_err = 0;
        wc.byte_len = 0;
        wc.imm_data = 0;
-       wc.qp_num = qp->ibqp.qp_num;
+       wc.qp = &qp->ibqp;
        wc.src_qp = 0;
        wc.wc_flags = 0;
        wc.pkey_index = 0;
@@ -255,7 +255,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp,
        wc->status = IB_WC_SUCCESS;
        wc->opcode = IB_WC_RECV;
        wc->vendor_err = 0;
-       wc->qp_num = qp->ibqp.qp_num;
+       wc->qp = &qp->ibqp;
        wc->src_qp = sqp->ibqp.qp_num;
        /* XXX do we know which pkey matched? Only needed for GSI. */
        wc->pkey_index = 0;
@@ -474,7 +474,7 @@ done:
                wc.vendor_err = 0;
                wc.opcode = IB_WC_SEND;
                wc.byte_len = len;
-               wc.qp_num = qp->ibqp.qp_num;
+               wc.qp = &qp->ibqp;
                wc.src_qp = 0;
                wc.wc_flags = 0;
                /* XXX initialize other fields? */
@@ -651,7 +651,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
        wc.status = IB_WC_SUCCESS;
        wc.opcode = IB_WC_RECV;
        wc.vendor_err = 0;
-       wc.qp_num = qp->ibqp.qp_num;
+       wc.qp = &qp->ibqp;
        wc.src_qp = src_qp;
        /* XXX do we know which pkey matched? Only needed for GSI. */
        wc.pkey_index = 0;
index 768df7265b81175408bb051f1b09d581363b13f8..968d1519761c50f64f28ed03e4f5ff8fd6d1e0b1 100644 (file)
@@ -1854,7 +1854,7 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey,
 
                memset(inbox + 256, 0, 256);
 
-               MTHCA_PUT(inbox, in_wc->qp_num,     MAD_IFC_MY_QPN_OFFSET);
+               MTHCA_PUT(inbox, in_wc->qp->qp_num, MAD_IFC_MY_QPN_OFFSET);
                MTHCA_PUT(inbox, in_wc->src_qp,     MAD_IFC_RQPN_OFFSET);
 
                val = in_wc->sl << 4;
index 1159c8a0f2c5211d3b9b6f9f2a2b59ea8de6872b..efd79ef109a6295b0544779914ed81317a4d7614 100644 (file)
@@ -534,7 +534,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev,
                }
        }
 
-       entry->qp_num = (*cur_qp)->qpn;
+       entry->qp = &(*cur_qp)->ibqp;
 
        if (is_send) {
                wq = &(*cur_qp)->sq;
index 72611fd15103302631a074a26f2cd2c0312d9b6d..5e8ac577f0ad1c33dd9cf65a71d18dd149848822 100644 (file)
@@ -548,6 +548,7 @@ static int srp_reconnect_target(struct srp_target_port *target)
        target->tx_head  = 0;
        target->tx_tail  = 0;
 
+       target->qp_in_error = 0;
        ret = srp_connect_target(target);
        if (ret)
                goto err;
@@ -878,6 +879,7 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr)
                        printk(KERN_ERR PFX "failed %s status %d\n",
                               wc.wr_id & SRP_OP_RECV ? "receive" : "send",
                               wc.status);
+                       target->qp_in_error = 1;
                        break;
                }
 
@@ -1337,6 +1339,8 @@ static int srp_abort(struct scsi_cmnd *scmnd)
 
        printk(KERN_ERR "SRP abort called\n");
 
+       if (target->qp_in_error)
+               return FAILED;
        if (srp_find_req(target, scmnd, &req))
                return FAILED;
        if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK))
@@ -1365,6 +1369,8 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
 
        printk(KERN_ERR "SRP reset_device called\n");
 
+       if (target->qp_in_error)
+               return FAILED;
        if (srp_find_req(target, scmnd, &req))
                return FAILED;
        if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET))
@@ -1801,6 +1807,7 @@ static ssize_t srp_create_target(struct class_device *class_dev,
                goto err_free;
        }
 
+       target->qp_in_error = 0;
        ret = srp_connect_target(target);
        if (ret) {
                printk(KERN_ERR PFX "Connection failed\n");
index c21772317b86957796a1d0163f571c9716285af0..2f3319c719a57a630fd1f39b74ec3c50ceab2a99 100644 (file)
@@ -158,6 +158,7 @@ struct srp_target_port {
        struct completion       done;
        int                     status;
        enum srp_target_state   state;
+       int                     qp_in_error;
 };
 
 struct srp_iu {
index 2ab7add78f94259c79106dceb6eeeeacbcf952c2..e21e490fedb04dc40b215a8715e93a9ffdb1cc7c 100644 (file)
 
 #include <linux/tifm.h>
 #include <linux/dma-mapping.h>
+#include <linux/freezer.h>
 
 #define DRIVER_NAME "tifm_7xx1"
-#define DRIVER_VERSION "0.6"
+#define DRIVER_VERSION "0.7"
 
 static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
 {
-       int cnt;
-       unsigned long flags;
-
-       spin_lock_irqsave(&fm->lock, flags);
-       if (!fm->inhibit_new_cards) {
-               for (cnt = 0; cnt < fm->max_sockets; cnt++) {
-                       if (fm->sockets[cnt] == sock) {
-                               fm->remove_mask |= (1 << cnt);
-                               queue_work(fm->wq, &fm->media_remover);
-                               break;
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&fm->lock, flags);
-}
-
-static void tifm_7xx1_remove_media(struct work_struct *work)
-{
-       struct tifm_adapter *fm =
-               container_of(work, struct tifm_adapter, media_remover);
        unsigned long flags;
-       int cnt;
-       struct tifm_dev *sock;
 
-       if (!class_device_get(&fm->cdev))
-               return;
        spin_lock_irqsave(&fm->lock, flags);
-       for (cnt = 0; cnt < fm->max_sockets; cnt++) {
-               if (fm->sockets[cnt] && (fm->remove_mask & (1 << cnt))) {
-                       printk(KERN_INFO DRIVER_NAME
-                              ": demand removing card from socket %d\n", cnt);
-                       sock = fm->sockets[cnt];
-                       fm->sockets[cnt] = NULL;
-                       fm->remove_mask &= ~(1 << cnt);
-
-                       writel(0x0e00, sock->addr + SOCK_CONTROL);
-
-                       writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-                               fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-                       writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-                               fm->addr + FM_SET_INTERRUPT_ENABLE);
-
-                       spin_unlock_irqrestore(&fm->lock, flags);
-                       device_unregister(&sock->dev);
-                       spin_lock_irqsave(&fm->lock, flags);
-               }
-       }
+       fm->socket_change_set |= 1 << sock->socket_id;
+       wake_up_all(&fm->change_set_notify);
        spin_unlock_irqrestore(&fm->lock, flags);
-       class_device_put(&fm->cdev);
 }
 
 static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
 {
        struct tifm_adapter *fm = dev_id;
+       struct tifm_dev *sock;
        unsigned int irq_status;
        unsigned int sock_irq_status, cnt;
 
@@ -84,42 +43,32 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
        if (irq_status & TIFM_IRQ_ENABLE) {
                writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
 
-               for (cnt = 0; cnt <  fm->max_sockets; cnt++) {
-                       sock_irq_status = (irq_status >> cnt) &
-                                       (TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK);
-
-                       if (fm->sockets[cnt]) {
-                               if (sock_irq_status &&
-                                               fm->sockets[cnt]->signal_irq)
-                                       sock_irq_status = fm->sockets[cnt]->
-                                               signal_irq(fm->sockets[cnt],
-                                                       sock_irq_status);
+               for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+                       sock = fm->sockets[cnt];
+                       sock_irq_status = (irq_status >> cnt)
+                                         & (TIFM_IRQ_FIFOMASK(1)
+                                            | TIFM_IRQ_CARDMASK(1));
 
-                               if (irq_status & (1 << cnt))
-                                       fm->remove_mask |= 1 << cnt;
-                       } else {
-                               if (irq_status & (1 << cnt))
-                                       fm->insert_mask |= 1 << cnt;
-                       }
+                       if (sock && sock_irq_status)
+                               sock->signal_irq(sock, sock_irq_status);
                }
+
+               fm->socket_change_set |= irq_status
+                                        & ((1 << fm->num_sockets) - 1);
        }
        writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
 
-       if (!fm->inhibit_new_cards) {
-               if (!fm->remove_mask && !fm->insert_mask) {
-                       writel(TIFM_IRQ_ENABLE,
-                               fm->addr + FM_SET_INTERRUPT_ENABLE);
-               } else {
-                       queue_work(fm->wq, &fm->media_remover);
-                       queue_work(fm->wq, &fm->media_inserter);
-               }
-       }
+       if (!fm->socket_change_set)
+               writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
+       else
+               wake_up_all(&fm->change_set_notify);
 
        spin_unlock(&fm->lock);
        return IRQ_HANDLED;
 }
 
-static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is_x2)
+static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr,
+                                                int is_x2)
 {
        unsigned int s_state;
        int cnt;
@@ -127,8 +76,8 @@ static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is
        writel(0x0e00, sock_addr + SOCK_CONTROL);
 
        for (cnt = 0; cnt < 100; cnt++) {
-               if (!(TIFM_SOCK_STATE_POWERED &
-                               readl(sock_addr + SOCK_PRESENT_STATE)))
+               if (!(TIFM_SOCK_STATE_POWERED
+                     & readl(sock_addr + SOCK_PRESENT_STATE)))
                        break;
                msleep(10);
        }
@@ -151,8 +100,8 @@ static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is
        }
 
        for (cnt = 0; cnt < 100; cnt++) {
-               if ((TIFM_SOCK_STATE_POWERED &
-                               readl(sock_addr + SOCK_PRESENT_STATE)))
+               if ((TIFM_SOCK_STATE_POWERED
+                    & readl(sock_addr + SOCK_PRESENT_STATE)))
                        break;
                msleep(10);
        }
@@ -170,130 +119,209 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
        return base_addr + ((sock_num + 1) << 10);
 }
 
-static void tifm_7xx1_insert_media(struct work_struct *work)
+static int tifm_7xx1_switch_media(void *data)
 {
-       struct tifm_adapter *fm =
-               container_of(work, struct tifm_adapter, media_inserter);
+       struct tifm_adapter *fm = data;
        unsigned long flags;
        tifm_media_id media_id;
        char *card_name = "xx";
-       int cnt, ok_to_register;
-       unsigned int insert_mask;
-       struct tifm_dev *new_sock = NULL;
+       int cnt, rc;
+       struct tifm_dev *sock;
+       unsigned int socket_change_set;
 
-       if (!class_device_get(&fm->cdev))
-               return;
-       spin_lock_irqsave(&fm->lock, flags);
-       insert_mask = fm->insert_mask;
-       fm->insert_mask = 0;
-       if (fm->inhibit_new_cards) {
+       while (1) {
+               rc = wait_event_interruptible(fm->change_set_notify,
+                                             fm->socket_change_set);
+               if (rc == -ERESTARTSYS)
+                       try_to_freeze();
+
+               spin_lock_irqsave(&fm->lock, flags);
+               socket_change_set = fm->socket_change_set;
+               fm->socket_change_set = 0;
+
+               dev_dbg(fm->dev, "checking media set %x\n",
+                       socket_change_set);
+
+               if (kthread_should_stop())
+                       socket_change_set = (1 << fm->num_sockets) - 1;
                spin_unlock_irqrestore(&fm->lock, flags);
-               class_device_put(&fm->cdev);
-               return;
-       }
-       spin_unlock_irqrestore(&fm->lock, flags);
 
-       for (cnt = 0; cnt < fm->max_sockets; cnt++) {
-               if (!(insert_mask & (1 << cnt)))
+               if (!socket_change_set)
                        continue;
 
-               media_id = tifm_7xx1_toggle_sock_power(tifm_7xx1_sock_addr(fm->addr, cnt),
-                                                      fm->max_sockets == 2);
-               if (media_id) {
-                       ok_to_register = 0;
-                       new_sock = tifm_alloc_device(fm, cnt);
-                       if (new_sock) {
-                               new_sock->addr = tifm_7xx1_sock_addr(fm->addr,
-                                                                       cnt);
-                               new_sock->media_id = media_id;
-                               switch (media_id) {
-                               case 1:
-                                       card_name = "xd";
-                                       break;
-                               case 2:
-                                       card_name = "ms";
-                                       break;
-                               case 3:
-                                       card_name = "sd";
-                                       break;
-                               default:
-                                       break;
-                               }
-                               snprintf(new_sock->dev.bus_id, BUS_ID_SIZE,
-                                       "tifm_%s%u:%u", card_name, fm->id, cnt);
+               spin_lock_irqsave(&fm->lock, flags);
+               for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+                       if (!(socket_change_set & (1 << cnt)))
+                               continue;
+                       sock = fm->sockets[cnt];
+                       if (sock) {
                                printk(KERN_INFO DRIVER_NAME
-                                       ": %s card detected in socket %d\n",
-                                       card_name, cnt);
+                                      ": demand removing card from socket %d\n",
+                                      cnt);
+                               fm->sockets[cnt] = NULL;
+                               spin_unlock_irqrestore(&fm->lock, flags);
+                               device_unregister(&sock->dev);
                                spin_lock_irqsave(&fm->lock, flags);
-                               if (!fm->sockets[cnt]) {
-                                       fm->sockets[cnt] = new_sock;
-                                       ok_to_register = 1;
+                               writel(0x0e00,
+                                      tifm_7xx1_sock_addr(fm->addr, cnt)
+                                      + SOCK_CONTROL);
+                       }
+                       if (kthread_should_stop())
+                               continue;
+
+                       spin_unlock_irqrestore(&fm->lock, flags);
+                       media_id = tifm_7xx1_toggle_sock_power(
+                                       tifm_7xx1_sock_addr(fm->addr, cnt),
+                                       fm->num_sockets == 2);
+                       if (media_id) {
+                               sock = tifm_alloc_device(fm);
+                               if (sock) {
+                                       sock->addr = tifm_7xx1_sock_addr(fm->addr,
+                                                                        cnt);
+                                       sock->media_id = media_id;
+                                       sock->socket_id = cnt;
+                                       switch (media_id) {
+                                       case 1:
+                                               card_name = "xd";
+                                               break;
+                                       case 2:
+                                               card_name = "ms";
+                                               break;
+                                       case 3:
+                                               card_name = "sd";
+                                               break;
+                                       default:
+                                               tifm_free_device(&sock->dev);
+                                               spin_lock_irqsave(&fm->lock, flags);
+                                               continue;
+                                       }
+                                       snprintf(sock->dev.bus_id, BUS_ID_SIZE,
+                                                "tifm_%s%u:%u", card_name,
+                                                fm->id, cnt);
+                                       printk(KERN_INFO DRIVER_NAME
+                                              ": %s card detected in socket %d\n",
+                                              card_name, cnt);
+                                       if (!device_register(&sock->dev)) {
+                                               spin_lock_irqsave(&fm->lock, flags);
+                                               if (!fm->sockets[cnt]) {
+                                                       fm->sockets[cnt] = sock;
+                                                       sock = NULL;
+                                               }
+                                               spin_unlock_irqrestore(&fm->lock, flags);
+                                       }
+                                       if (sock)
+                                               tifm_free_device(&sock->dev);
                                }
+                               spin_lock_irqsave(&fm->lock, flags);
+                       }
+               }
+
+               if (!kthread_should_stop()) {
+                       writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+                              | TIFM_IRQ_CARDMASK(socket_change_set),
+                              fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+                       writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+                              | TIFM_IRQ_CARDMASK(socket_change_set),
+                              fm->addr + FM_SET_INTERRUPT_ENABLE);
+                       writel(TIFM_IRQ_ENABLE,
+                              fm->addr + FM_SET_INTERRUPT_ENABLE);
+                       spin_unlock_irqrestore(&fm->lock, flags);
+               } else {
+                       for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+                               if (fm->sockets[cnt])
+                                       fm->socket_change_set |= 1 << cnt;
+                       }
+                       if (!fm->socket_change_set) {
+                               spin_unlock_irqrestore(&fm->lock, flags);
+                               return 0;
+                       } else {
                                spin_unlock_irqrestore(&fm->lock, flags);
-                               if (!ok_to_register ||
-                                           device_register(&new_sock->dev)) {
-                                       spin_lock_irqsave(&fm->lock, flags);
-                                       fm->sockets[cnt] = NULL;
-                                       spin_unlock_irqrestore(&fm->lock,
-                                                               flags);
-                                       tifm_free_device(&new_sock->dev);
-                               }
                        }
                }
-               writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-                      fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-               writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-                      fm->addr + FM_SET_INTERRUPT_ENABLE);
        }
-
-       writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
-       class_device_put(&fm->cdev);
+       return 0;
 }
 
+#ifdef CONFIG_PM
+
 static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state)
 {
-       struct tifm_adapter *fm = pci_get_drvdata(dev);
-       unsigned long flags;
+       dev_dbg(&dev->dev, "suspending host\n");
 
-       spin_lock_irqsave(&fm->lock, flags);
-       fm->inhibit_new_cards = 1;
-       fm->remove_mask = 0xf;
-       fm->insert_mask = 0;
-       writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-       spin_unlock_irqrestore(&fm->lock, flags);
-       flush_workqueue(fm->wq);
-
-       tifm_7xx1_remove_media(&fm->media_remover);
-
-       pci_set_power_state(dev, PCI_D3hot);
-        pci_disable_device(dev);
-        pci_save_state(dev);
+       pci_save_state(dev);
+       pci_enable_wake(dev, pci_choose_state(dev, state), 0);
+       pci_disable_device(dev);
+       pci_set_power_state(dev, pci_choose_state(dev, state));
        return 0;
 }
 
 static int tifm_7xx1_resume(struct pci_dev *dev)
 {
        struct tifm_adapter *fm = pci_get_drvdata(dev);
+       int cnt, rc;
        unsigned long flags;
+       tifm_media_id new_ids[fm->num_sockets];
 
+       pci_set_power_state(dev, PCI_D0);
        pci_restore_state(dev);
-        pci_enable_device(dev);
-        pci_set_power_state(dev, PCI_D0);
-        pci_set_master(dev);
+       rc = pci_enable_device(dev);
+       if (rc)
+               return rc;
+       pci_set_master(dev);
 
+       dev_dbg(&dev->dev, "resuming host\n");
+
+       for (cnt = 0; cnt < fm->num_sockets; cnt++)
+               new_ids[cnt] = tifm_7xx1_toggle_sock_power(
+                                       tifm_7xx1_sock_addr(fm->addr, cnt),
+                                       fm->num_sockets == 2);
        spin_lock_irqsave(&fm->lock, flags);
-       fm->inhibit_new_cards = 0;
-       writel(TIFM_IRQ_SETALL, fm->addr + FM_INTERRUPT_STATUS);
-       writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-       writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK,
-               fm->addr + FM_SET_INTERRUPT_ENABLE);
-       fm->insert_mask = 0xf;
+       fm->socket_change_set = 0;
+       for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+               if (fm->sockets[cnt]) {
+                       if (fm->sockets[cnt]->media_id == new_ids[cnt])
+                               fm->socket_change_set |= 1 << cnt;
+
+                       fm->sockets[cnt]->media_id = new_ids[cnt];
+               }
+       }
+
+       writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
+              fm->addr + FM_SET_INTERRUPT_ENABLE);
+       if (!fm->socket_change_set) {
+               spin_unlock_irqrestore(&fm->lock, flags);
+               return 0;
+       } else {
+               fm->socket_change_set = 0;
+               spin_unlock_irqrestore(&fm->lock, flags);
+       }
+
+       wait_event_timeout(fm->change_set_notify, fm->socket_change_set, HZ);
+
+       spin_lock_irqsave(&fm->lock, flags);
+       writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
+              | TIFM_IRQ_CARDMASK(fm->socket_change_set),
+              fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+       writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
+              | TIFM_IRQ_CARDMASK(fm->socket_change_set),
+              fm->addr + FM_SET_INTERRUPT_ENABLE);
+       writel(TIFM_IRQ_ENABLE,
+              fm->addr + FM_SET_INTERRUPT_ENABLE);
+       fm->socket_change_set = 0;
+
        spin_unlock_irqrestore(&fm->lock, flags);
        return 0;
 }
 
+#else
+
+#define tifm_7xx1_suspend NULL
+#define tifm_7xx1_resume NULL
+
+#endif /* CONFIG_PM */
+
 static int tifm_7xx1_probe(struct pci_dev *dev,
-                       const struct pci_device_id *dev_id)
+                          const struct pci_device_id *dev_id)
 {
        struct tifm_adapter *fm;
        int pci_dev_busy = 0;
@@ -324,19 +352,18 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
        }
 
        fm->dev = &dev->dev;
-       fm->max_sockets = (dev->device == 0x803B) ? 2 : 4;
-       fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->max_sockets,
-                               GFP_KERNEL);
+       fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM)
+                         ? 4 : 2;
+       fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets,
+                             GFP_KERNEL);
        if (!fm->sockets)
                goto err_out_free;
 
-       INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media);
-       INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media);
        fm->eject = tifm_7xx1_eject;
        pci_set_drvdata(dev, fm);
 
        fm->addr = ioremap(pci_resource_start(dev, 0),
-                               pci_resource_len(dev, 0));
+                          pci_resource_len(dev, 0));
        if (!fm->addr)
                goto err_out_free;
 
@@ -344,16 +371,15 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
        if (rc)
                goto err_out_unmap;
 
-       rc = tifm_add_adapter(fm);
+       init_waitqueue_head(&fm->change_set_notify);
+       rc = tifm_add_adapter(fm, tifm_7xx1_switch_media);
        if (rc)
                goto err_out_irq;
 
        writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-       writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK,
-               fm->addr + FM_SET_INTERRUPT_ENABLE);
-
-       fm->insert_mask = 0xf;
-
+       writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
+              fm->addr + FM_SET_INTERRUPT_ENABLE);
+       wake_up_process(fm->media_switcher);
        return 0;
 
 err_out_irq:
@@ -377,19 +403,15 @@ static void tifm_7xx1_remove(struct pci_dev *dev)
        struct tifm_adapter *fm = pci_get_drvdata(dev);
        unsigned long flags;
 
+       writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+       mmiowb();
+       free_irq(dev->irq, fm);
+
        spin_lock_irqsave(&fm->lock, flags);
-       fm->inhibit_new_cards = 1;
-       fm->remove_mask = 0xf;
-       fm->insert_mask = 0;
-       writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+       fm->socket_change_set = (1 << fm->num_sockets) - 1;
        spin_unlock_irqrestore(&fm->lock, flags);
 
-       flush_workqueue(fm->wq);
-
-       tifm_7xx1_remove_media(&fm->media_remover);
-
-       writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-       free_irq(dev->irq, fm);
+       kthread_stop(fm->media_switcher);
 
        tifm_remove_adapter(fm);
 
@@ -404,10 +426,12 @@ static void tifm_7xx1_remove(struct pci_dev *dev)
 }
 
 static struct pci_device_id tifm_7xx1_pci_tbl [] = {
-       { PCI_VENDOR_ID_TI, 0x8033, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         0 }, /* xx21 - the one I have */
-        { PCI_VENDOR_ID_TI, 0x803B, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
-         0 }, /* xx12 - should be also supported */
+       { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID,
+         PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */
+        { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID,
+         PCI_ANY_ID, 0, 0, 0 },
+       { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID,
+         PCI_ANY_ID, 0, 0, 0 },
        { }
 };
 
index d61df5c3ac367cd8e38650c1c44c19db99f3785d..6b10ebe9d9365d89bc40d1487c24a9ed86bf91e8 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/idr.h>
 
 #define DRIVER_NAME "tifm_core"
-#define DRIVER_VERSION "0.6"
+#define DRIVER_VERSION "0.7"
 
 static DEFINE_IDR(tifm_adapter_idr);
 static DEFINE_SPINLOCK(tifm_adapter_lock);
@@ -60,10 +60,41 @@ static int tifm_uevent(struct device *dev, char **envp, int num_envp,
        return 0;
 }
 
+#ifdef CONFIG_PM
+
+static int tifm_device_suspend(struct device *dev, pm_message_t state)
+{
+       struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
+       struct tifm_driver *drv = fm_dev->drv;
+
+       if (drv && drv->suspend)
+               return drv->suspend(fm_dev, state);
+       return 0;
+}
+
+static int tifm_device_resume(struct device *dev)
+{
+       struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
+       struct tifm_driver *drv = fm_dev->drv;
+
+       if (drv && drv->resume)
+               return drv->resume(fm_dev);
+       return 0;
+}
+
+#else
+
+#define tifm_device_suspend NULL
+#define tifm_device_resume NULL
+
+#endif /* CONFIG_PM */
+
 static struct bus_type tifm_bus_type = {
        .name    = "tifm",
        .match   = tifm_match,
        .uevent  = tifm_uevent,
+       .suspend = tifm_device_suspend,
+       .resume  = tifm_device_resume
 };
 
 static void tifm_free(struct class_device *cdev)
@@ -71,8 +102,6 @@ static void tifm_free(struct class_device *cdev)
        struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev);
 
        kfree(fm->sockets);
-       if (fm->wq)
-               destroy_workqueue(fm->wq);
        kfree(fm);
 }
 
@@ -101,7 +130,8 @@ void tifm_free_adapter(struct tifm_adapter *fm)
 }
 EXPORT_SYMBOL(tifm_free_adapter);
 
-int tifm_add_adapter(struct tifm_adapter *fm)
+int tifm_add_adapter(struct tifm_adapter *fm,
+                    int (*mediathreadfn)(void *data))
 {
        int rc;
 
@@ -113,10 +143,10 @@ int tifm_add_adapter(struct tifm_adapter *fm)
        spin_unlock(&tifm_adapter_lock);
        if (!rc) {
                snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
-               strncpy(fm->wq_name, fm->cdev.class_id, KOBJ_NAME_LEN);
+               fm->media_switcher = kthread_create(mediathreadfn,
+                                                   fm, "tifm/%u", fm->id);
 
-               fm->wq = create_singlethread_workqueue(fm->wq_name);
-               if (fm->wq)
+               if (!IS_ERR(fm->media_switcher))
                        return class_device_add(&fm->cdev);
 
                spin_lock(&tifm_adapter_lock);
@@ -141,27 +171,27 @@ EXPORT_SYMBOL(tifm_remove_adapter);
 void tifm_free_device(struct device *dev)
 {
        struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev);
-       if (fm_dev->wq)
-               destroy_workqueue(fm_dev->wq);
        kfree(fm_dev);
 }
 EXPORT_SYMBOL(tifm_free_device);
 
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id)
+static void tifm_dummy_signal_irq(struct tifm_dev *sock,
+                                 unsigned int sock_irq_status)
+{
+       return;
+}
+
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm)
 {
        struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL);
 
        if (dev) {
                spin_lock_init(&dev->lock);
-               snprintf(dev->wq_name, KOBJ_NAME_LEN, "tifm%u:%u", fm->id, id);
-               dev->wq = create_singlethread_workqueue(dev->wq_name);
-               if (!dev->wq) {
-                       kfree(dev);
-                       return NULL;
-               }
+
                dev->dev.parent = fm->dev;
                dev->dev.bus = &tifm_bus_type;
                dev->dev.release = tifm_free_device;
+               dev->signal_irq = tifm_dummy_signal_irq;
        }
        return dev;
 }
@@ -219,6 +249,7 @@ static int tifm_device_remove(struct device *dev)
        struct tifm_driver *drv = fm_dev->drv;
 
        if (drv) {
+               fm_dev->signal_irq = tifm_dummy_signal_irq;
                if (drv->remove)
                        drv->remove(fm_dev);
                fm_dev->drv = NULL;
@@ -233,6 +264,8 @@ int tifm_register_driver(struct tifm_driver *drv)
        drv->driver.bus = &tifm_bus_type;
        drv->driver.probe = tifm_device_probe;
        drv->driver.remove = tifm_device_remove;
+       drv->driver.suspend = tifm_device_suspend;
+       drv->driver.resume = tifm_device_resume;
 
        return driver_register(&drv->driver);
 }
index aa152f31851eb4efd8659250219558837e829759..2ce50f38e3c7d21c54d22b2be788bd6f4fc0acbd 100644 (file)
@@ -823,6 +823,9 @@ static int __init at91_mci_probe(struct platform_device *pdev)
        mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
        mmc->caps = MMC_CAP_BYTEBLOCK;
 
+       mmc->max_blk_size = 4095;
+       mmc->max_blk_count = mmc->max_req_size;
+
        host = mmc_priv(mmc);
        host->mmc = mmc;
        host->buffer = NULL;
index 800527cf40d5c58be4792a2001ca7ed1daa383e9..b834be261ab7ea163eaed79f592ad180458c0d62 100644 (file)
@@ -152,8 +152,9 @@ static inline int au1xmmc_card_inserted(struct au1xmmc_host *host)
                ? 1 : 0;
 }
 
-static inline int au1xmmc_card_readonly(struct au1xmmc_host *host)
+static int au1xmmc_card_readonly(struct mmc_host *mmc)
 {
+       struct au1xmmc_host *host = mmc_priv(mmc);
        return (bcsr->status & au1xmmc_card_table[host->id].wpstatus)
                ? 1 : 0;
 }
@@ -193,6 +194,8 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
        u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT);
 
        switch (mmc_resp_type(cmd)) {
+       case MMC_RSP_NONE:
+               break;
        case MMC_RSP_R1:
                mmccmd |= SD_CMD_RT_1;
                break;
@@ -205,6 +208,10 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait,
        case MMC_RSP_R3:
                mmccmd |= SD_CMD_RT_3;
                break;
+       default:
+               printk(KERN_INFO "au1xmmc: unhandled response type %02x\n",
+                       mmc_resp_type(cmd));
+               return MMC_ERR_INVALID;
        }
 
        switch(cmd->opcode) {
@@ -878,6 +885,7 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host)
 static const struct mmc_host_ops au1xmmc_ops = {
        .request        = au1xmmc_request,
        .set_ios        = au1xmmc_set_ios,
+       .get_ro         = au1xmmc_card_readonly,
 };
 
 static int __devinit au1xmmc_probe(struct platform_device *pdev)
@@ -914,6 +922,9 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
                mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE;
                mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT;
 
+               mmc->max_blk_size = 2048;
+               mmc->max_blk_count = 512;
+
                mmc->ocr_avail = AU1XMMC_OCR;
 
                host = mmc_priv(mmc);
index bfb9ff693208fa51c81667622a699cd5748916c0..b060d4bfba29b731a37653c79d361be5b82b3c83 100644 (file)
@@ -958,8 +958,10 @@ static int imxmci_probe(struct platform_device *pdev)
        /* MMC core transfer sizes tunable parameters */
        mmc->max_hw_segs = 64;
        mmc->max_phys_segs = 64;
-       mmc->max_sectors = 64;          /* default 1 << (PAGE_CACHE_SHIFT - 9) */
        mmc->max_seg_size = 64*512;     /* default PAGE_CACHE_SIZE */
+       mmc->max_req_size = 64*512;     /* default PAGE_CACHE_SIZE */
+       mmc->max_blk_size = 2048;
+       mmc->max_blk_count = 65535;
 
        host = mmc_priv(mmc);
        host->mmc = mmc;
index 6f2a282e2b9759c0511cf5501a0bd4e9bd501e3f..5046a1661342f2e13ac8417c14ed697163368390 100644 (file)
@@ -103,11 +103,16 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
                 mmc_hostname(host), mrq->cmd->opcode,
                 mrq->cmd->arg, mrq->cmd->flags);
 
-       WARN_ON(host->card_busy == NULL);
+       WARN_ON(!host->claimed);
 
        mrq->cmd->error = 0;
        mrq->cmd->mrq = mrq;
        if (mrq->data) {
+               BUG_ON(mrq->data->blksz > host->max_blk_size);
+               BUG_ON(mrq->data->blocks > host->max_blk_count);
+               BUG_ON(mrq->data->blocks * mrq->data->blksz >
+                       host->max_req_size);
+
                mrq->cmd->data = mrq->data;
                mrq->data->error = 0;
                mrq->data->mrq = mrq;
@@ -157,7 +162,7 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
 {
        struct mmc_request mrq;
 
-       BUG_ON(host->card_busy == NULL);
+       BUG_ON(!host->claimed);
 
        memset(&mrq, 0, sizeof(struct mmc_request));
 
@@ -195,7 +200,7 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
 
        int i, err;
 
-       BUG_ON(host->card_busy == NULL);
+       BUG_ON(!host->claimed);
        BUG_ON(retries < 0);
 
        err = MMC_ERR_INVALID;
@@ -289,7 +294,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
                else
                        limit_us = 100000;
 
-               if (timeout_us > limit_us) {
+               /*
+                * SDHC cards always use these fixed values.
+                */
+               if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
                        data->timeout_ns = limit_us * 1000;
                        data->timeout_clks = 0;
                }
@@ -320,14 +328,14 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
        spin_lock_irqsave(&host->lock, flags);
        while (1) {
                set_current_state(TASK_UNINTERRUPTIBLE);
-               if (host->card_busy == NULL)
+               if (!host->claimed)
                        break;
                spin_unlock_irqrestore(&host->lock, flags);
                schedule();
                spin_lock_irqsave(&host->lock, flags);
        }
        set_current_state(TASK_RUNNING);
-       host->card_busy = card;
+       host->claimed = 1;
        spin_unlock_irqrestore(&host->lock, flags);
        remove_wait_queue(&host->wq, &wait);
 
@@ -353,10 +361,10 @@ void mmc_release_host(struct mmc_host *host)
 {
        unsigned long flags;
 
-       BUG_ON(host->card_busy == NULL);
+       BUG_ON(!host->claimed);
 
        spin_lock_irqsave(&host->lock, flags);
-       host->card_busy = NULL;
+       host->claimed = 0;
        spin_unlock_irqrestore(&host->lock, flags);
 
        wake_up(&host->wq);
@@ -372,7 +380,7 @@ static inline void mmc_set_ios(struct mmc_host *host)
                 mmc_hostname(host), ios->clock, ios->bus_mode,
                 ios->power_mode, ios->chip_select, ios->vdd,
                 ios->bus_width);
-       
+
        host->ops->set_ios(host, ios);
 }
 
@@ -381,7 +389,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
        int err;
        struct mmc_command cmd;
 
-       BUG_ON(host->card_busy == NULL);
+       BUG_ON(!host->claimed);
 
        if (host->card_selected == card)
                return MMC_ERR_NONE;
@@ -588,34 +596,65 @@ static void mmc_decode_csd(struct mmc_card *card)
 
        if (mmc_card_sd(card)) {
                csd_struct = UNSTUFF_BITS(resp, 126, 2);
-               if (csd_struct != 0) {
+
+               switch (csd_struct) {
+               case 0:
+                       m = UNSTUFF_BITS(resp, 115, 4);
+                       e = UNSTUFF_BITS(resp, 112, 3);
+                       csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+                       csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+                       m = UNSTUFF_BITS(resp, 99, 4);
+                       e = UNSTUFF_BITS(resp, 96, 3);
+                       csd->max_dtr      = tran_exp[e] * tran_mant[m];
+                       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+                       e = UNSTUFF_BITS(resp, 47, 3);
+                       m = UNSTUFF_BITS(resp, 62, 12);
+                       csd->capacity     = (1 + m) << (e + 2);
+
+                       csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+                       csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+                       csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+                       csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+                       csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+                       csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+                       csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+                       break;
+               case 1:
+                       /*
+                        * This is a block-addressed SDHC card. Most
+                        * interesting fields are unused and have fixed
+                        * values. To avoid getting tripped by buggy cards,
+                        * we assume those fixed values ourselves.
+                        */
+                       mmc_card_set_blockaddr(card);
+
+                       csd->tacc_ns     = 0; /* Unused */
+                       csd->tacc_clks   = 0; /* Unused */
+
+                       m = UNSTUFF_BITS(resp, 99, 4);
+                       e = UNSTUFF_BITS(resp, 96, 3);
+                       csd->max_dtr      = tran_exp[e] * tran_mant[m];
+                       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+                       m = UNSTUFF_BITS(resp, 48, 22);
+                       csd->capacity     = (1 + m) << 10;
+
+                       csd->read_blkbits = 9;
+                       csd->read_partial = 0;
+                       csd->write_misalign = 0;
+                       csd->read_misalign = 0;
+                       csd->r2w_factor = 4; /* Unused */
+                       csd->write_blkbits = 9;
+                       csd->write_partial = 0;
+                       break;
+               default:
                        printk("%s: unrecognised CSD structure version %d\n",
                                mmc_hostname(card->host), csd_struct);
                        mmc_card_set_bad(card);
                        return;
                }
-
-               m = UNSTUFF_BITS(resp, 115, 4);
-               e = UNSTUFF_BITS(resp, 112, 3);
-               csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-               csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-               m = UNSTUFF_BITS(resp, 99, 4);
-               e = UNSTUFF_BITS(resp, 96, 3);
-               csd->max_dtr      = tran_exp[e] * tran_mant[m];
-               csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
-
-               e = UNSTUFF_BITS(resp, 47, 3);
-               m = UNSTUFF_BITS(resp, 62, 12);
-               csd->capacity     = (1 + m) << (e + 2);
-
-               csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-               csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-               csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-               csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-               csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-               csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-               csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
        } else {
                /*
                 * We only understand CSD structure v1.1 and v1.2.
@@ -848,6 +887,41 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
        return err;
 }
 
+static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
+{
+       struct mmc_command cmd;
+       int err, sd2;
+       static const u8 test_pattern = 0xAA;
+
+       /*
+       * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
+       * before SD_APP_OP_COND. This command will harmlessly fail for
+       * SD 1.0 cards.
+       */
+       cmd.opcode = SD_SEND_IF_COND;
+       cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
+       cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
+
+       err = mmc_wait_for_cmd(host, &cmd, 0);
+       if (err == MMC_ERR_NONE) {
+               if ((cmd.resp[0] & 0xFF) == test_pattern) {
+                       sd2 = 1;
+               } else {
+                       sd2 = 0;
+                       err = MMC_ERR_FAILED;
+               }
+       } else {
+               /*
+                * Treat errors as SD 1.0 card.
+                */
+               sd2 = 0;
+               err = MMC_ERR_NONE;
+       }
+       if (rsd2)
+               *rsd2 = sd2;
+       return err;
+}
+
 /*
  * Discover cards by requesting their CID.  If this command
  * times out, it is not an error; there are no further cards
@@ -1018,7 +1092,8 @@ static void mmc_process_ext_csds(struct mmc_host *host)
                mmc_wait_for_req(host, &mrq);
 
                if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
+                       printk("%s: unable to read EXT_CSD, performance "
+                               "might suffer.\n", mmc_hostname(card->host));
                        continue;
                }
 
@@ -1034,7 +1109,6 @@ static void mmc_process_ext_csds(struct mmc_host *host)
                        printk("%s: card is mmc v4 but doesn't support "
                               "any high-speed modes.\n",
                                mmc_hostname(card->host));
-                       mmc_card_set_bad(card);
                        continue;
                }
 
@@ -1215,7 +1289,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
                mmc_wait_for_req(host, &mrq);
 
                if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
+                       printk("%s: unable to read switch capabilities, "
+                               "performance might suffer.\n",
+                               mmc_hostname(card->host));
                        continue;
                }
 
@@ -1247,12 +1323,8 @@ static void mmc_read_switch_caps(struct mmc_host *host)
 
                mmc_wait_for_req(host, &mrq);
 
-               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
-                       continue;
-               }
-
-               if ((status[16] & 0xF) != 1) {
+               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE ||
+                       (status[16] & 0xF) != 1) {
                        printk(KERN_WARNING "%s: Problem switching card "
                                "into high-speed mode!\n",
                                mmc_hostname(host));
@@ -1334,6 +1406,10 @@ static void mmc_setup(struct mmc_host *host)
                mmc_power_up(host);
                mmc_idle_cards(host);
 
+               err = mmc_send_if_cond(host, host->ocr_avail, NULL);
+               if (err != MMC_ERR_NONE) {
+                       return;
+               }
                err = mmc_send_app_op_cond(host, 0, &ocr);
 
                /*
@@ -1386,10 +1462,21 @@ static void mmc_setup(struct mmc_host *host)
         * all get the idea that they should be ready for CMD2.
         * (My SanDisk card seems to need this.)
         */
-       if (host->mode == MMC_MODE_SD)
-               mmc_send_app_op_cond(host, host->ocr, NULL);
-       else
+       if (host->mode == MMC_MODE_SD) {
+               int err, sd2;
+               err = mmc_send_if_cond(host, host->ocr, &sd2);
+               if (err == MMC_ERR_NONE) {
+                       /*
+                       * If SD_SEND_IF_COND indicates an SD 2.0
+                       * compliant card and we should set bit 30
+                       * of the ocr to indicate that we can handle
+                       * block-addressed SDHC cards.
+                       */
+                       mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
+               }
+       } else {
                mmc_send_op_cond(host, host->ocr, NULL);
+       }
 
        mmc_discover_cards(host);
 
@@ -1519,8 +1606,11 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
                 */
                host->max_hw_segs = 1;
                host->max_phys_segs = 1;
-               host->max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
                host->max_seg_size = PAGE_CACHE_SIZE;
+
+               host->max_req_size = PAGE_CACHE_SIZE;
+               host->max_blk_size = 512;
+               host->max_blk_count = PAGE_CACHE_SIZE / 512;
        }
 
        return host;
index 87713572293f0d3044e077e1b9944617dc14ce1f..05ba8ace70e7801071a2a614ad4e9d74d13f1502 100644 (file)
@@ -237,13 +237,17 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                brq.mrq.cmd = &brq.cmd;
                brq.mrq.data = &brq.data;
 
-               brq.cmd.arg = req->sector << 9;
+               brq.cmd.arg = req->sector;
+               if (!mmc_card_blockaddr(card))
+                       brq.cmd.arg <<= 9;
                brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
                brq.data.blksz = 1 << md->block_bits;
-               brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
                brq.stop.opcode = MMC_STOP_TRANSMISSION;
                brq.stop.arg = 0;
                brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
+               brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
+               if (brq.data.blocks > card->host->max_blk_count)
+                       brq.data.blocks = card->host->max_blk_count;
 
                mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ);
 
@@ -375,9 +379,10 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                spin_unlock_irq(&md->lock);
        }
 
+flush_queue:
+
        mmc_card_release_host(card);
 
-flush_queue:
        spin_lock_irq(&md->lock);
        while (ret) {
                ret = end_that_request_chunk(req, 0,
@@ -494,6 +499,10 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
        struct mmc_command cmd;
        int err;
 
+       /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */
+       if (mmc_card_blockaddr(card))
+               return 0;
+
        mmc_card_claim_host(card);
        cmd.opcode = MMC_SET_BLOCKLEN;
        cmd.arg = 1 << md->block_bits;
index 3e35a43819fba1a75c00d7cdac55265cda17f9f8..c27e42645cdb240933456fb872e1510eeb7bc5d5 100644 (file)
@@ -147,7 +147,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
 
        blk_queue_prep_rq(mq->queue, mmc_prep_request);
        blk_queue_bounce_limit(mq->queue, limit);
-       blk_queue_max_sectors(mq->queue, host->max_sectors);
+       blk_queue_max_sectors(mq->queue, host->max_req_size / 512);
        blk_queue_max_phys_segments(mq->queue, host->max_phys_segs);
        blk_queue_max_hw_segments(mq->queue, host->max_hw_segs);
        blk_queue_max_segment_size(mq->queue, host->max_seg_size);
index e334acd045bced56ac88edf5850bde81297d8087..d32698b02d7fe6e2b9f5e1df829caeada5e33170 100644 (file)
@@ -199,7 +199,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
        memset(card, 0, sizeof(struct mmc_card));
        card->host = host;
        device_initialize(&card->dev);
-       card->dev.parent = mmc_dev(host);
+       card->dev.parent = mmc_classdev(host);
        card->dev.bus = &mmc_bus_type;
        card->dev.release = mmc_release_card;
 }
index ccfe6561be240ec65dadbbab2ea56ce0166cd001..5941dd951e824bfc8a1ef9a0290590fbc8e0cefe 100644 (file)
@@ -524,15 +524,24 @@ static int mmci_probe(struct amba_device *dev, void *id)
        /*
         * Since we only have a 16-bit data length register, we must
         * ensure that we don't exceed 2^16-1 bytes in a single request.
-        * Choose 64 (512-byte) sectors as the limit.
         */
-       mmc->max_sectors = 64;
+       mmc->max_req_size = 65535;
 
        /*
         * Set the maximum segment size.  Since we aren't doing DMA
         * (yet) we are only limited by the data length register.
         */
-       mmc->max_seg_size = mmc->max_sectors << 9;
+       mmc->max_seg_size = mmc->max_req_size;
+
+       /*
+        * Block size can be up to 2048 bytes, but must be a power of two.
+        */
+       mmc->max_blk_size = 2048;
+
+       /*
+        * No limit on the number of blocks transferred.
+        */
+       mmc->max_blk_count = mmc->max_req_size;
 
        spin_lock_init(&host->lock);
 
index d30540b2761420cff6bf445f761b8d0b27b34b40..1e96a2f65022eee03e234b14bae7e92fb0c30c02 100644 (file)
@@ -1099,8 +1099,10 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
         */
        mmc->max_phys_segs = 32;
        mmc->max_hw_segs = 32;
-       mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */
-       mmc->max_seg_size = mmc->max_sectors * 512;
+       mmc->max_blk_size = 2048;       /* BLEN is 11 bits (+1) */
+       mmc->max_blk_count = 2048;      /* NBLK is 11 bits (+1) */
+       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+       mmc->max_seg_size = mmc->max_req_size;
 
        if (host->power_pin >= 0) {
                if ((ret = omap_request_gpio(host->power_pin)) != 0) {
index 6073d998b11f3ee1164d3209be639a21ba640be3..9774fc68b61a0c56cae19d96276aab5bd18e56cc 100644 (file)
@@ -450,6 +450,16 @@ static int pxamci_probe(struct platform_device *pdev)
         */
        mmc->max_seg_size = PAGE_SIZE;
 
+       /*
+        * Block length register is 10 bits.
+        */
+       mmc->max_blk_size = 1023;
+
+       /*
+        * Block count register is 16 bits.
+        */
+       mmc->max_blk_count = 65535;
+
        host = mmc_priv(mmc);
        host->mmc = mmc;
        host->dma = -1;
index c2d13d7e99111f986e4c4d136f3c72ba95a5f4d8..4bf1fea5e2c405acccfa1b7ebbc069a2d323a787 100644 (file)
@@ -37,6 +37,7 @@ static unsigned int debug_quirks = 0;
 #define SDHCI_QUIRK_FORCE_DMA                          (1<<1)
 /* Controller doesn't like some resets when there is no card inserted. */
 #define SDHCI_QUIRK_NO_CARD_NO_RESET                   (1<<2)
+#define SDHCI_QUIRK_SINGLE_POWER_WRITE                 (1<<3)
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
        {
@@ -65,6 +66,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
                .driver_data    = SDHCI_QUIRK_FORCE_DMA,
        },
 
+       {
+               .vendor         = PCI_VENDOR_ID_ENE,
+               .device         = PCI_DEVICE_ID_ENE_CB712_SD,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = SDHCI_QUIRK_SINGLE_POWER_WRITE,
+       },
+
        {       /* Generic SD host controller */
                PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
        },
@@ -197,15 +206,9 @@ static void sdhci_deactivate_led(struct sdhci_host *host)
  *                                                                           *
 \*****************************************************************************/
 
-static inline char* sdhci_kmap_sg(struct sdhci_host* host)
+static inline char* sdhci_sg_to_buffer(struct sdhci_host* host)
 {
-       host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ);
-       return host->mapped_sg + host->cur_sg->offset;
-}
-
-static inline void sdhci_kunmap_sg(struct sdhci_host* host)
-{
-       kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
+       return page_address(host->cur_sg->page) + host->cur_sg->offset;
 }
 
 static inline int sdhci_next_sg(struct sdhci_host* host)
@@ -240,7 +243,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
        chunk_remain = 0;
        data = 0;
 
-       buffer = sdhci_kmap_sg(host) + host->offset;
+       buffer = sdhci_sg_to_buffer(host) + host->offset;
 
        while (blksize) {
                if (chunk_remain == 0) {
@@ -264,16 +267,13 @@ static void sdhci_read_block_pio(struct sdhci_host *host)
                }
 
                if (host->remain == 0) {
-                       sdhci_kunmap_sg(host);
                        if (sdhci_next_sg(host) == 0) {
                                BUG_ON(blksize != 0);
                                return;
                        }
-                       buffer = sdhci_kmap_sg(host);
+                       buffer = sdhci_sg_to_buffer(host);
                }
        }
-
-       sdhci_kunmap_sg(host);
 }
 
 static void sdhci_write_block_pio(struct sdhci_host *host)
@@ -290,7 +290,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host)
        data = 0;
 
        bytes = 0;
-       buffer = sdhci_kmap_sg(host) + host->offset;
+       buffer = sdhci_sg_to_buffer(host) + host->offset;
 
        while (blksize) {
                size = min(host->size, host->remain);
@@ -314,16 +314,13 @@ static void sdhci_write_block_pio(struct sdhci_host *host)
                }
 
                if (host->remain == 0) {
-                       sdhci_kunmap_sg(host);
                        if (sdhci_next_sg(host) == 0) {
                                BUG_ON(blksize != 0);
                                return;
                        }
-                       buffer = sdhci_kmap_sg(host);
+                       buffer = sdhci_sg_to_buffer(host);
                }
        }
-
-       sdhci_kunmap_sg(host);
 }
 
 static void sdhci_transfer_pio(struct sdhci_host *host)
@@ -372,7 +369,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 
        /* Sanity checks */
        BUG_ON(data->blksz * data->blocks > 524288);
-       BUG_ON(data->blksz > host->max_block);
+       BUG_ON(data->blksz > host->mmc->max_blk_size);
        BUG_ON(data->blocks > 65535);
 
        /* timeout in us */
@@ -674,10 +671,17 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
        if (host->power == power)
                return;
 
-       writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
-
-       if (power == (unsigned short)-1)
+       if (power == (unsigned short)-1) {
+               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
                goto out;
+       }
+
+       /*
+        * Spec says that we should clear the power reg before setting
+        * a new value. Some controllers don't seem to like this though.
+        */
+       if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE))
+               writeb(0, host->ioaddr + SDHCI_POWER_CONTROL);
 
        pwr = SDHCI_POWER_ON;
 
@@ -1109,7 +1113,9 @@ static int sdhci_resume (struct pci_dev *pdev)
 
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
-       pci_enable_device(pdev);
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
 
        for (i = 0;i < chip->num_slots;i++) {
                if (!chip->hosts[i])
@@ -1274,15 +1280,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        if (caps & SDHCI_TIMEOUT_CLK_UNIT)
                host->timeout_clk *= 1000;
 
-       host->max_block = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
-       if (host->max_block >= 3) {
-               printk(KERN_ERR "%s: Invalid maximum block size.\n",
-                       host->slot_descr);
-               ret = -ENODEV;
-               goto unmap;
-       }
-       host->max_block = 512 << host->max_block;
-
        /*
         * Set host parameters.
         */
@@ -1294,9 +1291,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        mmc->ocr_avail = 0;
        if (caps & SDHCI_CAN_VDD_330)
                mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34;
-       else if (caps & SDHCI_CAN_VDD_300)
+       if (caps & SDHCI_CAN_VDD_300)
                mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31;
-       else if (caps & SDHCI_CAN_VDD_180)
+       if (caps & SDHCI_CAN_VDD_180)
                mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19;
 
        if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) {
@@ -1326,15 +1323,33 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
 
        /*
         * Maximum number of sectors in one transfer. Limited by DMA boundary
-        * size (512KiB), which means (512 KiB/512=) 1024 entries.
+        * size (512KiB).
         */
-       mmc->max_sectors = 1024;
+       mmc->max_req_size = 524288;
 
        /*
         * Maximum segment size. Could be one segment with the maximum number
-        * of sectors.
+        * of bytes.
+        */
+       mmc->max_seg_size = mmc->max_req_size;
+
+       /*
+        * Maximum block size. This varies from controller to controller and
+        * is specified in the capabilities register.
+        */
+       mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
+       if (mmc->max_blk_size >= 3) {
+               printk(KERN_ERR "%s: Invalid maximum block size.\n",
+                       host->slot_descr);
+               ret = -ENODEV;
+               goto unmap;
+       }
+       mmc->max_blk_size = 512 << mmc->max_blk_size;
+
+       /*
+        * Maximum block count.
         */
-       mmc->max_seg_size = mmc->max_sectors * 512;
+       mmc->max_blk_count = 65535;
 
        /*
         * Init tasklets.
index f9d1a0a6f03a97fae3e0b1ebd7a129999877c42a..e324f0a623dcc44c4f469464c379c7a805c40527 100644 (file)
@@ -174,7 +174,6 @@ struct sdhci_host {
 
        unsigned int            max_clk;        /* Max possible freq (MHz) */
        unsigned int            timeout_clk;    /* Timeout freq (KHz) */
-       unsigned int            max_block;      /* Max block size (bytes) */
 
        unsigned int            clock;          /* Current clock (MHz) */
        unsigned short          power;          /* Current voltage */
@@ -184,7 +183,6 @@ struct sdhci_host {
        struct mmc_data         *data;          /* Current data request */
 
        struct scatterlist      *cur_sg;        /* We're working on this */
-       char                    *mapped_sg;     /* This is where it's mapped */
        int                     num_sg;         /* Entries left */
        int                     offset;         /* Offset into current sg */
        int                     remain;         /* Bytes left in current */
index fa4a52886b97c9a358eab60cca56c05b5cd219fa..e65f8a0a9349c4145711938a9a6a3de5e158413e 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/io.h>
 
 #define DRIVER_NAME "tifm_sd"
-#define DRIVER_VERSION "0.6"
+#define DRIVER_VERSION "0.7"
 
 static int no_dma = 0;
 static int fixed_timeout = 0;
@@ -79,7 +79,6 @@ typedef enum {
 
 enum {
        FIFO_RDY   = 0x0001,     /* hardware dependent value */
-       HOST_REG   = 0x0002,
        EJECT      = 0x0004,
        EJECT_DONE = 0x0008,
        CARD_BUSY  = 0x0010,
@@ -95,46 +94,53 @@ struct tifm_sd {
        card_state_t        state;
        unsigned int        clk_freq;
        unsigned int        clk_div;
-       unsigned long       timeout_jiffies; // software timeout - 2 sec
+       unsigned long       timeout_jiffies;
 
+       struct tasklet_struct finish_tasklet;
+       struct timer_list     timer;
        struct mmc_request    *req;
-       struct work_struct    cmd_handler;
-       struct delayed_work   abort_handler;
-       wait_queue_head_t     can_eject;
+       wait_queue_head_t     notify;
 
        size_t                written_blocks;
-       char                  *buffer;
        size_t                buffer_size;
        size_t                buffer_pos;
 
 };
 
+static char* tifm_sd_data_buffer(struct mmc_data *data)
+{
+       return page_address(data->sg->page) + data->sg->offset;
+}
+
 static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host,
-                                       unsigned int host_status)
+                                unsigned int host_status)
 {
        struct mmc_command *cmd = host->req->cmd;
        unsigned int t_val = 0, cnt = 0;
+       char *buffer;
 
        if (host_status & TIFM_MMCSD_BRS) {
                /* in non-dma rx mode BRS fires when fifo is still not empty */
-               if (host->buffer && (cmd->data->flags & MMC_DATA_READ)) {
+               if (no_dma && (cmd->data->flags & MMC_DATA_READ)) {
+                       buffer = tifm_sd_data_buffer(host->req->data);
                        while (host->buffer_size > host->buffer_pos) {
                                t_val = readl(sock->addr + SOCK_MMCSD_DATA);
-                               host->buffer[host->buffer_pos++] = t_val & 0xff;
-                               host->buffer[host->buffer_pos++] =
+                               buffer[host->buffer_pos++] = t_val & 0xff;
+                               buffer[host->buffer_pos++] =
                                                        (t_val >> 8) & 0xff;
                        }
                }
                return 1;
-       } else if (host->buffer) {
+       } else if (no_dma) {
+               buffer = tifm_sd_data_buffer(host->req->data);
                if ((cmd->data->flags & MMC_DATA_READ) &&
                                (host_status & TIFM_MMCSD_AF)) {
                        for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
                                t_val = readl(sock->addr + SOCK_MMCSD_DATA);
                                if (host->buffer_size > host->buffer_pos) {
-                                       host->buffer[host->buffer_pos++] =
+                                       buffer[host->buffer_pos++] =
                                                        t_val & 0xff;
-                                       host->buffer[host->buffer_pos++] =
+                                       buffer[host->buffer_pos++] =
                                                        (t_val >> 8) & 0xff;
                                }
                        }
@@ -142,11 +148,12 @@ static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host,
                           && (host_status & TIFM_MMCSD_AE)) {
                        for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
                                if (host->buffer_size > host->buffer_pos) {
-                                       t_val = host->buffer[host->buffer_pos++] & 0x00ff;
-                                       t_val |= ((host->buffer[host->buffer_pos++]) << 8)
-                                                & 0xff00;
+                                       t_val = buffer[host->buffer_pos++]
+                                               & 0x00ff;
+                                       t_val |= ((buffer[host->buffer_pos++])
+                                                 << 8) & 0xff00;
                                        writel(t_val,
-                                               sock->addr + SOCK_MMCSD_DATA);
+                                              sock->addr + SOCK_MMCSD_DATA);
                                }
                        }
                }
@@ -206,7 +213,7 @@ static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd)
                cmd_mask |= TIFM_MMCSD_READ;
 
        dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n",
-                               cmd->opcode, cmd->arg, cmd_mask);
+               cmd->opcode, cmd->arg, cmd_mask);
 
        writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH);
        writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW);
@@ -239,65 +246,78 @@ change_state:
                        tifm_sd_fetch_resp(cmd, sock);
                        if (cmd->data) {
                                host->state = BRS;
-                       } else
+                       } else {
                                host->state = READY;
+                       }
                        goto change_state;
                }
                break;
        case BRS:
                if (tifm_sd_transfer_data(sock, host, host_status)) {
-                       if (!host->req->stop) {
-                               if (cmd->data->flags & MMC_DATA_WRITE) {
-                                       host->state = CARD;
+                       if (cmd->data->flags & MMC_DATA_WRITE) {
+                               host->state = CARD;
+                       } else {
+                               if (no_dma) {
+                                       if (host->req->stop) {
+                                               tifm_sd_exec(host, host->req->stop);
+                                               host->state = SCMD;
+                                       } else {
+                                               host->state = READY;
+                                       }
                                } else {
-                                       host->state =
-                                               host->buffer ? READY : FIFO;
+                                       host->state = FIFO;
                                }
-                               goto change_state;
                        }
-                       tifm_sd_exec(host, host->req->stop);
-                       host->state = SCMD;
+                       goto change_state;
                }
                break;
        case SCMD:
                if (host_status & TIFM_MMCSD_EOC) {
                        tifm_sd_fetch_resp(host->req->stop, sock);
-                       if (cmd->error) {
-                               host->state = READY;
-                       } else if (cmd->data->flags & MMC_DATA_WRITE) {
-                               host->state = CARD;
-                       } else {
-                               host->state = host->buffer ? READY : FIFO;
-                       }
+                       host->state = READY;
                        goto change_state;
                }
                break;
        case CARD:
+               dev_dbg(&sock->dev, "waiting for CARD, have %zd blocks\n",
+                       host->written_blocks);
                if (!(host->flags & CARD_BUSY)
                    && (host->written_blocks == cmd->data->blocks)) {
-                       host->state = host->buffer ? READY : FIFO;
+                       if (no_dma) {
+                               if (host->req->stop) {
+                                       tifm_sd_exec(host, host->req->stop);
+                                       host->state = SCMD;
+                               } else {
+                                       host->state = READY;
+                               }
+                       } else {
+                               host->state = FIFO;
+                       }
                        goto change_state;
                }
                break;
        case FIFO:
                if (host->flags & FIFO_RDY) {
-                       host->state = READY;
                        host->flags &= ~FIFO_RDY;
+                       if (host->req->stop) {
+                               tifm_sd_exec(host, host->req->stop);
+                               host->state = SCMD;
+                       } else {
+                               host->state = READY;
+                       }
                        goto change_state;
                }
                break;
        case READY:
-               queue_work(sock->wq, &host->cmd_handler);
+               tasklet_schedule(&host->finish_tasklet);
                return;
        }
 
-       queue_delayed_work(sock->wq, &host->abort_handler,
-                               host->timeout_jiffies);
 }
 
 /* Called from interrupt handler */
-static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock,
-                                       unsigned int sock_irq_status)
+static void tifm_sd_signal_irq(struct tifm_dev *sock,
+                              unsigned int sock_irq_status)
 {
        struct tifm_sd *host;
        unsigned int host_status = 0, fifo_status = 0;
@@ -305,7 +325,6 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock,
 
        spin_lock(&sock->lock);
        host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock));
-       cancel_delayed_work(&host->abort_handler);
 
        if (sock_irq_status & FIFO_EVENT) {
                fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS);
@@ -318,19 +337,17 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock,
                host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
                writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
 
-               if (!(host->flags & HOST_REG))
-                       queue_work(sock->wq, &host->cmd_handler);
                if (!host->req)
                        goto done;
 
                if (host_status & TIFM_MMCSD_ERRMASK) {
                        if (host_status & TIFM_MMCSD_CERR)
                                error_code = MMC_ERR_FAILED;
-                       else if (host_status &
-                                       (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO))
+                       else if (host_status
+                                & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO))
                                error_code = MMC_ERR_TIMEOUT;
-                       else if (host_status &
-                                       (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC))
+                       else if (host_status
+                                & (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC))
                                error_code = MMC_ERR_BADCRC;
 
                        writel(TIFM_FIFO_INT_SETALL,
@@ -340,12 +357,11 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock,
                        if (host->req->stop) {
                                if (host->state == SCMD) {
                                        host->req->stop->error = error_code;
-                               } else if(host->state == BRS) {
+                               } else if (host->state == BRS
+                                          || host->state == CARD
+                                          || host->state == FIFO) {
                                        host->req->cmd->error = error_code;
                                        tifm_sd_exec(host, host->req->stop);
-                                       queue_delayed_work(sock->wq,
-                                               &host->abort_handler,
-                                               host->timeout_jiffies);
                                        host->state = SCMD;
                                        goto done;
                                } else {
@@ -359,8 +375,8 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock,
 
                if (host_status & TIFM_MMCSD_CB)
                        host->flags |= CARD_BUSY;
-               if ((host_status & TIFM_MMCSD_EOFB) &&
-                               (host->flags & CARD_BUSY)) {
+               if ((host_status & TIFM_MMCSD_EOFB)
+                   && (host->flags & CARD_BUSY)) {
                        host->written_blocks++;
                        host->flags &= ~CARD_BUSY;
                }
@@ -370,22 +386,22 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock,
                tifm_sd_process_cmd(sock, host, host_status);
 done:
        dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n",
-                       host_status, fifo_status);
+               host_status, fifo_status);
        spin_unlock(&sock->lock);
-       return sock_irq_status;
 }
 
-static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd)
+static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd)
 {
-       struct tifm_dev *sock = card->dev;
+       struct tifm_dev *sock = host->dev;
        unsigned int dest_cnt;
 
        /* DMA style IO */
-
+       dev_dbg(&sock->dev, "setting dma for %d blocks\n",
+               cmd->data->blocks);
        writel(TIFM_FIFO_INT_SETALL,
-               sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+              sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
        writel(ilog2(cmd->data->blksz) - 2,
-                       sock->addr + SOCK_FIFO_PAGE_SIZE);
+              sock->addr + SOCK_FIFO_PAGE_SIZE);
        writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL);
        writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
 
@@ -399,7 +415,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd)
        if (cmd->data->flags & MMC_DATA_WRITE) {
                writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
                writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN,
-                       sock->addr + SOCK_DMA_CONTROL);
+                      sock->addr + SOCK_DMA_CONTROL);
        } else {
                writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
                writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL);
@@ -407,7 +423,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd)
 }
 
 static void tifm_sd_set_data_timeout(struct tifm_sd *host,
-                                       struct mmc_data *data)
+                                    struct mmc_data *data)
 {
        struct tifm_dev *sock = host->dev;
        unsigned int data_timeout = data->timeout_clks;
@@ -416,22 +432,21 @@ static void tifm_sd_set_data_timeout(struct tifm_sd *host,
                return;
 
        data_timeout += data->timeout_ns /
-                       ((1000000000 / host->clk_freq) * host->clk_div);
-       data_timeout *= 10; // call it fudge factor for now
+                       ((1000000000UL / host->clk_freq) * host->clk_div);
 
        if (data_timeout < 0xffff) {
-               writel((~TIFM_MMCSD_DPE) &
-                               readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-                      sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
                writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+               writel((~TIFM_MMCSD_DPE)
+                      & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+                      sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
        } else {
-               writel(TIFM_MMCSD_DPE |
-                               readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
-                       sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
                data_timeout = (data_timeout >> 10) + 1;
-               if(data_timeout > 0xffff)
+               if (data_timeout > 0xffff)
                        data_timeout = 0;       /* set to unlimited */
                writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO);
+               writel(TIFM_MMCSD_DPE
+                      | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG),
+                      sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG);
        }
 }
 
@@ -474,11 +489,10 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq)
        }
 
        host->req = mrq;
+       mod_timer(&host->timer, jiffies + host->timeout_jiffies);
        host->state = CMD;
-       queue_delayed_work(sock->wq, &host->abort_handler,
-                               host->timeout_jiffies);
        writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-               sock->addr + SOCK_CONTROL);
+              sock->addr + SOCK_CONTROL);
        tifm_sd_exec(host, mrq->cmd);
        spin_unlock_irqrestore(&sock->lock, flags);
        return;
@@ -493,9 +507,9 @@ err_out:
        mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_end_cmd(struct work_struct *work)
+static void tifm_sd_end_cmd(unsigned long data)
 {
-       struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler);
+       struct tifm_sd *host = (struct tifm_sd*)data;
        struct tifm_dev *sock = host->dev;
        struct mmc_host *mmc = tifm_get_drvdata(sock);
        struct mmc_request *mrq;
@@ -504,6 +518,7 @@ static void tifm_sd_end_cmd(struct work_struct *work)
 
        spin_lock_irqsave(&sock->lock, flags);
 
+       del_timer(&host->timer);
        mrq = host->req;
        host->req = NULL;
        host->state = IDLE;
@@ -517,8 +532,8 @@ static void tifm_sd_end_cmd(struct work_struct *work)
        r_data = mrq->cmd->data;
        if (r_data) {
                if (r_data->flags & MMC_DATA_WRITE) {
-                       r_data->bytes_xfered = host->written_blocks *
-                                               r_data->blksz;
+                       r_data->bytes_xfered = host->written_blocks
+                                              * r_data->blksz;
                } else {
                        r_data->bytes_xfered = r_data->blocks -
                                readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
@@ -532,7 +547,7 @@ static void tifm_sd_end_cmd(struct work_struct *work)
        }
 
        writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-                       sock->addr + SOCK_CONTROL);
+              sock->addr + SOCK_CONTROL);
 
        spin_unlock_irqrestore(&sock->lock, flags);
        mmc_request_done(mmc, mrq);
@@ -544,15 +559,6 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq)
        struct tifm_dev *sock = host->dev;
        unsigned long flags;
        struct mmc_data *r_data = mrq->cmd->data;
-       char *t_buffer = NULL;
-
-       if (r_data) {
-               t_buffer = kmap(r_data->sg->page);
-               if (!t_buffer) {
-                       printk(KERN_ERR DRIVER_NAME ": kmap failed\n");
-                       goto err_out;
-               }
-       }
 
        spin_lock_irqsave(&sock->lock, flags);
        if (host->flags & EJECT) {
@@ -569,15 +575,14 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq)
        if (r_data) {
                tifm_sd_set_data_timeout(host, r_data);
 
-               host->buffer = t_buffer + r_data->sg->offset;
-               host->buffer_size = mrq->cmd->data->blocks *
-                                       mrq->cmd->data->blksz;
+               host->buffer_size = mrq->cmd->data->blocks
+                                   * mrq->cmd->data->blksz;
 
-               writel(TIFM_MMCSD_BUFINT |
-                               readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
+               writel(TIFM_MMCSD_BUFINT
+                      | readl(sock->addr + SOCK_MMCSD_INT_ENABLE),
                       sock->addr + SOCK_MMCSD_INT_ENABLE);
-               writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) |
-                               (TIFM_MMCSD_FIFO_SIZE - 1),
+               writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8)
+                      | (TIFM_MMCSD_FIFO_SIZE - 1),
                       sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
 
                host->written_blocks = 0;
@@ -588,26 +593,22 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq)
        }
 
        host->req = mrq;
+       mod_timer(&host->timer, jiffies + host->timeout_jiffies);
        host->state = CMD;
-       queue_delayed_work(sock->wq, &host->abort_handler,
-                               host->timeout_jiffies);
        writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL),
-               sock->addr + SOCK_CONTROL);
+              sock->addr + SOCK_CONTROL);
        tifm_sd_exec(host, mrq->cmd);
        spin_unlock_irqrestore(&sock->lock, flags);
        return;
 
 err_out:
-       if (t_buffer)
-               kunmap(r_data->sg->page);
-
        mrq->cmd->error = MMC_ERR_TIMEOUT;
        mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_end_cmd_nodma(struct work_struct *work)
+static void tifm_sd_end_cmd_nodma(unsigned long data)
 {
-       struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler);
+       struct tifm_sd *host = (struct tifm_sd*)data;
        struct tifm_dev *sock = host->dev;
        struct mmc_host *mmc = tifm_get_drvdata(sock);
        struct mmc_request *mrq;
@@ -616,6 +617,7 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work)
 
        spin_lock_irqsave(&sock->lock, flags);
 
+       del_timer(&host->timer);
        mrq = host->req;
        host->req = NULL;
        host->state = IDLE;
@@ -633,8 +635,8 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work)
                        sock->addr + SOCK_MMCSD_INT_ENABLE);
 
                if (r_data->flags & MMC_DATA_WRITE) {
-                       r_data->bytes_xfered = host->written_blocks *
-                                               r_data->blksz;
+                       r_data->bytes_xfered = host->written_blocks
+                                              * r_data->blksz;
                } else {
                        r_data->bytes_xfered = r_data->blocks -
                                readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1;
@@ -642,29 +644,44 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work)
                        r_data->bytes_xfered += r_data->blksz -
                                readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
                }
-               host->buffer = NULL;
                host->buffer_pos = 0;
                host->buffer_size = 0;
        }
 
        writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL),
-                       sock->addr + SOCK_CONTROL);
+              sock->addr + SOCK_CONTROL);
 
        spin_unlock_irqrestore(&sock->lock, flags);
 
-        if (r_data)
-               kunmap(r_data->sg->page);
-
        mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_abort(struct work_struct *work)
+static void tifm_sd_terminate(struct tifm_sd *host)
+{
+       struct tifm_dev *sock = host->dev;
+       unsigned long flags;
+
+       writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+       mmiowb();
+       spin_lock_irqsave(&sock->lock, flags);
+       host->flags |= EJECT;
+       if (host->req) {
+               writel(TIFM_FIFO_INT_SETALL,
+                      sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
+               writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+               tasklet_schedule(&host->finish_tasklet);
+       }
+       spin_unlock_irqrestore(&sock->lock, flags);
+}
+
+static void tifm_sd_abort(unsigned long data)
 {
-       struct tifm_sd *host =
-               container_of(work, struct tifm_sd, abort_handler.work);
+       struct tifm_sd *host = (struct tifm_sd*)data;
 
        printk(KERN_ERR DRIVER_NAME
-               ": card failed to respond for a long period of time");
+              ": card failed to respond for a long period of time");
+
+       tifm_sd_terminate(host);
        tifm_eject(host->dev);
 }
 
@@ -683,9 +700,9 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG),
                       sock->addr + SOCK_MMCSD_CONFIG);
        } else {
-               writel((~TIFM_MMCSD_4BBUS) &
-                               readl(sock->addr + SOCK_MMCSD_CONFIG),
-                       sock->addr + SOCK_MMCSD_CONFIG);
+               writel((~TIFM_MMCSD_4BBUS)
+                      & readl(sock->addr + SOCK_MMCSD_CONFIG),
+                      sock->addr + SOCK_MMCSD_CONFIG);
        }
 
        if (ios->clock) {
@@ -704,23 +721,24 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                if ((20000000 / clk_div1) > (24000000 / clk_div2)) {
                        host->clk_freq = 20000000;
                        host->clk_div = clk_div1;
-                       writel((~TIFM_CTRL_FAST_CLK) &
-                                       readl(sock->addr + SOCK_CONTROL),
-                               sock->addr + SOCK_CONTROL);
+                       writel((~TIFM_CTRL_FAST_CLK)
+                              & readl(sock->addr + SOCK_CONTROL),
+                              sock->addr + SOCK_CONTROL);
                } else {
                        host->clk_freq = 24000000;
                        host->clk_div = clk_div2;
-                       writel(TIFM_CTRL_FAST_CLK |
-                                       readl(sock->addr + SOCK_CONTROL),
-                               sock->addr + SOCK_CONTROL);
+                       writel(TIFM_CTRL_FAST_CLK
+                              | readl(sock->addr + SOCK_CONTROL),
+                              sock->addr + SOCK_CONTROL);
                }
        } else {
                host->clk_div = 0;
        }
        host->clk_div &= TIFM_MMCSD_CLKMASK;
-       writel(host->clk_div | ((~TIFM_MMCSD_CLKMASK) &
-                       readl(sock->addr + SOCK_MMCSD_CONFIG)),
-               sock->addr + SOCK_MMCSD_CONFIG);
+       writel(host->clk_div
+              | ((~TIFM_MMCSD_CLKMASK)
+                 & readl(sock->addr + SOCK_MMCSD_CONFIG)),
+              sock->addr + SOCK_MMCSD_CONFIG);
 
        if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
                host->flags |= OPENDRAIN;
@@ -734,7 +752,7 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        // allow removal.
        if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) {
                host->flags |= EJECT_DONE;
-               wake_up_all(&host->can_eject);
+               wake_up_all(&host->notify);
        }
 
        spin_unlock_irqrestore(&sock->lock, flags);
@@ -762,20 +780,67 @@ static struct mmc_host_ops tifm_sd_ops = {
        .get_ro  = tifm_sd_ro
 };
 
-static void tifm_sd_register_host(struct work_struct *work)
+static int tifm_sd_initialize_host(struct tifm_sd *host)
 {
-       struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler);
+       int rc;
+       unsigned int host_status = 0;
        struct tifm_dev *sock = host->dev;
-       struct mmc_host *mmc = tifm_get_drvdata(sock);
-       unsigned long flags;
 
-       spin_lock_irqsave(&sock->lock, flags);
-       host->flags |= HOST_REG;
-       PREPARE_WORK(&host->cmd_handler,
-                       no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd);
-       spin_unlock_irqrestore(&sock->lock, flags);
-       dev_dbg(&sock->dev, "adding host\n");
-       mmc_add_host(mmc);
+       writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
+       mmiowb();
+       host->clk_div = 61;
+       host->clk_freq = 20000000;
+       writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
+       writel(host->clk_div | TIFM_MMCSD_POWER,
+              sock->addr + SOCK_MMCSD_CONFIG);
+
+       /* wait up to 0.51 sec for reset */
+       for (rc = 2; rc <= 256; rc <<= 1) {
+               if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
+                       rc = 0;
+                       break;
+               }
+               msleep(rc);
+       }
+
+       if (rc) {
+               printk(KERN_ERR DRIVER_NAME
+                      ": controller failed to reset\n");
+               return -ENODEV;
+       }
+
+       writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
+       writel(host->clk_div | TIFM_MMCSD_POWER,
+              sock->addr + SOCK_MMCSD_CONFIG);
+       writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
+
+       // command timeout fixed to 64 clocks for now
+       writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO);
+       writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
+
+       /* INAB should take much less than reset */
+       for (rc = 1; rc <= 16; rc <<= 1) {
+               host_status = readl(sock->addr + SOCK_MMCSD_STATUS);
+               writel(host_status, sock->addr + SOCK_MMCSD_STATUS);
+               if (!(host_status & TIFM_MMCSD_ERRMASK)
+                   && (host_status & TIFM_MMCSD_EOC)) {
+                       rc = 0;
+                       break;
+               }
+               msleep(rc);
+       }
+
+       if (rc) {
+               printk(KERN_ERR DRIVER_NAME
+                      ": card not ready - probe failed on initialization\n");
+               return -ENODEV;
+       }
+
+       writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK,
+              sock->addr + SOCK_MMCSD_INT_ENABLE);
+       mmiowb();
+
+       return 0;
 }
 
 static int tifm_sd_probe(struct tifm_dev *sock)
@@ -784,8 +849,8 @@ static int tifm_sd_probe(struct tifm_dev *sock)
        struct tifm_sd *host;
        int rc = -EIO;
 
-       if (!(TIFM_SOCK_STATE_OCCUPIED &
-                       readl(sock->addr + SOCK_PRESENT_STATE))) {
+       if (!(TIFM_SOCK_STATE_OCCUPIED
+             & readl(sock->addr + SOCK_PRESENT_STATE))) {
                printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n");
                return rc;
        }
@@ -795,109 +860,99 @@ static int tifm_sd_probe(struct tifm_dev *sock)
                return -ENOMEM;
 
        host = mmc_priv(mmc);
-       host->dev = sock;
-       host->clk_div = 61;
-       init_waitqueue_head(&host->can_eject);
-       INIT_WORK(&host->cmd_handler, tifm_sd_register_host);
-       INIT_DELAYED_WORK(&host->abort_handler, tifm_sd_abort);
-
        tifm_set_drvdata(sock, mmc);
-       sock->signal_irq = tifm_sd_signal_irq;
-
-       host->clk_freq = 20000000;
+       host->dev = sock;
        host->timeout_jiffies = msecs_to_jiffies(1000);
 
+       init_waitqueue_head(&host->notify);
+       tasklet_init(&host->finish_tasklet,
+                    no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd,
+                    (unsigned long)host);
+       setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host);
+
        tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request;
        mmc->ops = &tifm_sd_ops;
        mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-       mmc->caps = MMC_CAP_4_BIT_DATA;
+       mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE;
        mmc->f_min = 20000000 / 60;
        mmc->f_max = 24000000;
        mmc->max_hw_segs = 1;
        mmc->max_phys_segs = 1;
-       mmc->max_sectors = 127;
-       mmc->max_seg_size = mmc->max_sectors << 11; //2k maximum hw block length
-
-       writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-       writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL);
-       writel(host->clk_div | TIFM_MMCSD_POWER,
-                       sock->addr + SOCK_MMCSD_CONFIG);
+       // limited by DMA counter - it's safer to stick with
+       // block counter has 11 bits though
+       mmc->max_blk_count = 256;
+       // 2k maximum hw block length
+       mmc->max_blk_size = 2048;
+       mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+       mmc->max_seg_size = mmc->max_req_size;
+       sock->signal_irq = tifm_sd_signal_irq;
+       rc = tifm_sd_initialize_host(host);
 
-       for (rc = 0; rc < 50; rc++) {
-               /* Wait for reset ack */
-               if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) {
-                       rc = 0;
-                       break;
-               }
-               msleep(10);
-        }
+       if (!rc)
+               rc = mmc_add_host(mmc);
+       if (rc)
+               goto out_free_mmc;
 
-       if (rc) {
-               printk(KERN_ERR DRIVER_NAME
-                       ": card not ready - probe failed\n");
-               mmc_free_host(mmc);
-               return -ENODEV;
-       }
+       return 0;
+out_free_mmc:
+       mmc_free_host(mmc);
+       return rc;
+}
 
-       writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS);
-       writel(host->clk_div | TIFM_MMCSD_POWER,
-                       sock->addr + SOCK_MMCSD_CONFIG);
-       writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG);
-       writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK,
-                       sock->addr + SOCK_MMCSD_INT_ENABLE);
+static void tifm_sd_remove(struct tifm_dev *sock)
+{
+       struct mmc_host *mmc = tifm_get_drvdata(sock);
+       struct tifm_sd *host = mmc_priv(mmc);
 
-       writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); // command timeout 64 clocks for now
-       writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND);
-       writel(host->clk_div | TIFM_MMCSD_POWER,
-                       sock->addr + SOCK_MMCSD_CONFIG);
+       del_timer_sync(&host->timer);
+       tifm_sd_terminate(host);
+       wait_event_timeout(host->notify, host->flags & EJECT_DONE,
+                          host->timeout_jiffies);
+       tasklet_kill(&host->finish_tasklet);
+       mmc_remove_host(mmc);
 
-       queue_delayed_work(sock->wq, &host->abort_handler,
-                       host->timeout_jiffies);
+       /* The meaning of the bit majority in this constant is unknown. */
+       writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
+              sock->addr + SOCK_CONTROL);
 
-       return 0;
+       tifm_set_drvdata(sock, NULL);
+       mmc_free_host(mmc);
 }
 
-static int tifm_sd_host_is_down(struct tifm_dev *sock)
+#ifdef CONFIG_PM
+
+static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state)
 {
        struct mmc_host *mmc = tifm_get_drvdata(sock);
-       struct tifm_sd *host = mmc_priv(mmc);
-       unsigned long flags;
-       int rc = 0;
+       int rc;
 
-       spin_lock_irqsave(&sock->lock, flags);
-       rc = (host->flags & EJECT_DONE);
-       spin_unlock_irqrestore(&sock->lock, flags);
+       rc = mmc_suspend_host(mmc, state);
+       /* The meaning of the bit majority in this constant is unknown. */
+       writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
+              sock->addr + SOCK_CONTROL);
        return rc;
 }
 
-static void tifm_sd_remove(struct tifm_dev *sock)
+static int tifm_sd_resume(struct tifm_dev *sock)
 {
        struct mmc_host *mmc = tifm_get_drvdata(sock);
        struct tifm_sd *host = mmc_priv(mmc);
-       unsigned long flags;
 
-       spin_lock_irqsave(&sock->lock, flags);
-       host->flags |= EJECT;
-       if (host->req)
-               queue_work(sock->wq, &host->cmd_handler);
-       spin_unlock_irqrestore(&sock->lock, flags);
-       wait_event_timeout(host->can_eject, tifm_sd_host_is_down(sock),
-                               host->timeout_jiffies);
+       if (sock->media_id != FM_SD
+           || tifm_sd_initialize_host(host)) {
+               tifm_eject(sock);
+               return 0;
+       } else {
+               return mmc_resume_host(mmc);
+       }
+}
 
-       if (host->flags & HOST_REG)
-               mmc_remove_host(mmc);
+#else
 
-       /* The meaning of the bit majority in this constant is unknown. */
-       writel(0xfff8 & readl(sock->addr + SOCK_CONTROL),
-               sock->addr + SOCK_CONTROL);
-       writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE);
-       writel(TIFM_FIFO_INT_SETALL,
-               sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR);
-       writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET);
+#define tifm_sd_suspend NULL
+#define tifm_sd_resume NULL
 
-       tifm_set_drvdata(sock, NULL);
-       mmc_free_host(mmc);
-}
+#endif /* CONFIG_PM */
 
 static tifm_media_id tifm_sd_id_tbl[] = {
        FM_SD, 0
@@ -910,7 +965,9 @@ static struct tifm_driver tifm_sd_driver = {
        },
        .id_table = tifm_sd_id_tbl,
        .probe    = tifm_sd_probe,
-       .remove   = tifm_sd_remove
+       .remove   = tifm_sd_remove,
+       .suspend  = tifm_sd_suspend,
+       .resume   = tifm_sd_resume
 };
 
 static int __init tifm_sd_init(void)
index 7a282672f8e9037d9995859e9fbdb31504ecbf94..a44d8777ab9f21011074a9beffa4e718d7a34acf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver
  *
- *  Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved.
+ *  Copyright (C) 2004-2006 Pierre Ossman, All Rights Reserved.
  *
  * 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
@@ -272,16 +272,9 @@ static inline int wbsd_next_sg(struct wbsd_host *host)
        return host->num_sg;
 }
 
-static inline char *wbsd_kmap_sg(struct wbsd_host *host)
+static inline char *wbsd_sg_to_buffer(struct wbsd_host *host)
 {
-       host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ) +
-               host->cur_sg->offset;
-       return host->mapped_sg;
-}
-
-static inline void wbsd_kunmap_sg(struct wbsd_host *host)
-{
-       kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ);
+       return page_address(host->cur_sg->page) + host->cur_sg->offset;
 }
 
 static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
@@ -302,12 +295,11 @@ static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
         * we do not transfer too much.
         */
        for (i = 0; i < len; i++) {
-               sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset;
+               sgbuf = page_address(sg[i].page) + sg[i].offset;
                if (size < sg[i].length)
                        memcpy(dmabuf, sgbuf, size);
                else
                        memcpy(dmabuf, sgbuf, sg[i].length);
-               kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ);
                dmabuf += sg[i].length;
 
                if (size < sg[i].length)
@@ -347,7 +339,7 @@ static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
         * we do not transfer too much.
         */
        for (i = 0; i < len; i++) {
-               sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset;
+               sgbuf = page_address(sg[i].page) + sg[i].offset;
                if (size < sg[i].length)
                        memcpy(sgbuf, dmabuf, size);
                else
@@ -497,7 +489,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
        if (data->bytes_xfered == host->size)
                return;
 
-       buffer = wbsd_kmap_sg(host) + host->offset;
+       buffer = wbsd_sg_to_buffer(host) + host->offset;
 
        /*
         * Drain the fifo. This has a tendency to loop longer
@@ -526,17 +518,13 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
                        /*
                         * Transfer done?
                         */
-                       if (data->bytes_xfered == host->size) {
-                               wbsd_kunmap_sg(host);
+                       if (data->bytes_xfered == host->size)
                                return;
-                       }
 
                        /*
                         * End of scatter list entry?
                         */
                        if (host->remain == 0) {
-                               wbsd_kunmap_sg(host);
-
                                /*
                                 * Get next entry. Check if last.
                                 */
@@ -554,13 +542,11 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
                                        return;
                                }
 
-                               buffer = wbsd_kmap_sg(host);
+                               buffer = wbsd_sg_to_buffer(host);
                        }
                }
        }
 
-       wbsd_kunmap_sg(host);
-
        /*
         * This is a very dirty hack to solve a
         * hardware problem. The chip doesn't trigger
@@ -583,7 +569,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
        if (data->bytes_xfered == host->size)
                return;
 
-       buffer = wbsd_kmap_sg(host) + host->offset;
+       buffer = wbsd_sg_to_buffer(host) + host->offset;
 
        /*
         * Fill the fifo. This has a tendency to loop longer
@@ -612,17 +598,13 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
                        /*
                         * Transfer done?
                         */
-                       if (data->bytes_xfered == host->size) {
-                               wbsd_kunmap_sg(host);
+                       if (data->bytes_xfered == host->size)
                                return;
-                       }
 
                        /*
                         * End of scatter list entry?
                         */
                        if (host->remain == 0) {
-                               wbsd_kunmap_sg(host);
-
                                /*
                                 * Get next entry. Check if last.
                                 */
@@ -640,13 +622,11 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
                                        return;
                                }
 
-                               buffer = wbsd_kmap_sg(host);
+                               buffer = wbsd_sg_to_buffer(host);
                        }
                }
        }
 
-       wbsd_kunmap_sg(host);
-
        /*
         * The controller stops sending interrupts for
         * 'FIFO empty' under certain conditions. So we
@@ -909,6 +889,45 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq)
         * transfered.
         */
        if (cmd->data && (cmd->error == MMC_ERR_NONE)) {
+               /*
+                * The hardware is so delightfully stupid that it has a list
+                * of "data" commands. If a command isn't on this list, it'll
+                * just go back to the idle state and won't send any data
+                * interrupts.
+                */
+               switch (cmd->opcode) {
+               case 11:
+               case 17:
+               case 18:
+               case 20:
+               case 24:
+               case 25:
+               case 26:
+               case 27:
+               case 30:
+               case 42:
+               case 56:
+                       break;
+
+               /* ACMDs. We don't keep track of state, so we just treat them
+                * like any other command. */
+               case 51:
+                       break;
+
+               default:
+#ifdef CONFIG_MMC_DEBUG
+                       printk(KERN_WARNING "%s: Data command %d is not "
+                               "supported by this controller.\n",
+                               mmc_hostname(host->mmc), cmd->opcode);
+#endif
+                       cmd->data->error = MMC_ERR_INVALID;
+
+                       if (cmd->data->stop)
+                               wbsd_send_command(host, cmd->data->stop);
+
+                       goto done;
+               };
+
                /*
                 * Dirty fix for hardware bug.
                 */
@@ -1343,16 +1362,27 @@ static int __devinit wbsd_alloc_mmc(struct device *dev)
        mmc->max_phys_segs = 128;
 
        /*
-        * Maximum number of sectors in one transfer. Also limited by 64kB
-        * buffer.
+        * Maximum request size. Also limited by 64KiB buffer.
         */
-       mmc->max_sectors = 128;
+       mmc->max_req_size = 65536;
 
        /*
         * Maximum segment size. Could be one segment with the maximum number
-        * of segments.
+        * of bytes.
+        */
+       mmc->max_seg_size = mmc->max_req_size;
+
+       /*
+        * Maximum block size. We have 12 bits (= 4095) but have to subtract
+        * space for CRC. So the maximum is 4095 - 4*2 = 4087.
+        */
+       mmc->max_blk_size = 4087;
+
+       /*
+        * Maximum block count. There is no real limit so the maximum
+        * request size will be the only restriction.
         */
-       mmc->max_seg_size = mmc->max_sectors * 512;
+       mmc->max_blk_count = mmc->max_req_size;
 
        dev_set_drvdata(dev, mmc);
 
index 6072993f01e3f9debc30c0933856fea23a55190e..d06718b0e2abd7593693cff591fe88326b446eef 100644 (file)
@@ -154,7 +154,6 @@ struct wbsd_host
 
        struct scatterlist*     cur_sg;         /* Current SG entry */
        unsigned int            num_sg;         /* Number of entries left */
-       void*                   mapped_sg;      /* vaddr of mapped sg */
 
        unsigned int            offset;         /* Offset into current entry */
        unsigned int            remain;         /* Data left in curren entry */
index ae89b9b88743462538ba6069b268a13642530045..165af398fdead8b181edc120ae91ed6a364f1cb3 100644 (file)
@@ -103,14 +103,8 @@ config CCW_CONSOLE
        depends on TN3215_CONSOLE || TN3270_CONSOLE
        default y
  
-config SCLP
-       bool "Support for SCLP"
-       help
-         Include support for the SCLP interface to the service element.
-
 config SCLP_TTY
        bool "Support for SCLP line mode terminal"
-       depends on SCLP
        help
          Include support for IBM SCLP line-mode terminals.
 
@@ -123,7 +117,6 @@ config SCLP_CONSOLE
 
 config SCLP_VT220_TTY
        bool "Support for SCLP VT220-compatible terminal"
-       depends on SCLP
        help
          Include support for an IBM SCLP VT220-compatible terminal.
 
@@ -136,7 +129,6 @@ config SCLP_VT220_CONSOLE
 
 config SCLP_CPI
        tristate "Control-Program Identification"
-       depends on SCLP
        help
          This option enables the hardware console interface for system
          identification. This is commonly used for workload management and
index 9803c9352d78e8e88bffbd49b82794e6c06444c3..5a888704a8d002ca0d846308f51e052ec4a3301b 100644 (file)
@@ -2,6 +2,8 @@
 # Makefile for the S/390 specific device drivers
 #
 
+CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
+
 obj-y += s390mach.o sysinfo.o s390_rdev.o
 obj-y += cio/ block/ char/ crypto/ net/ scsi/
 
index 492b68bcd7cc0e26be5cb44fc192f417c7402954..eb5dc62f0d9c25cdace3239f3a5aacdf613f72ee 100644 (file)
@@ -37,6 +37,7 @@
  */
 debug_info_t *dasd_debug_area;
 struct dasd_discipline *dasd_diag_discipline_pointer;
+void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 
 MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
 MODULE_DESCRIPTION("Linux on S/390 DASD device driver,"
@@ -51,7 +52,6 @@ static int  dasd_alloc_queue(struct dasd_device * device);
 static void dasd_setup_queue(struct dasd_device * device);
 static void dasd_free_queue(struct dasd_device * device);
 static void dasd_flush_request_queue(struct dasd_device *);
-static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 static int dasd_flush_ccw_queue(struct dasd_device *, int);
 static void dasd_tasklet(struct dasd_device *);
 static void do_kick_device(struct work_struct *);
@@ -483,7 +483,7 @@ unsigned int dasd_profile_level = DASD_PROFILE_OFF;
 /*
  * Add profiling information for cqr before execution.
  */
-static inline void
+static void
 dasd_profile_start(struct dasd_device *device, struct dasd_ccw_req * cqr,
                   struct request *req)
 {
@@ -505,7 +505,7 @@ dasd_profile_start(struct dasd_device *device, struct dasd_ccw_req * cqr,
 /*
  * Add profiling information for cqr after execution.
  */
-static inline void
+static void
 dasd_profile_end(struct dasd_device *device, struct dasd_ccw_req * cqr,
                 struct request *req)
 {
@@ -1022,8 +1022,6 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
                 irb->scsw.cstat == 0 &&
                 !irb->esw.esw0.erw.cons)
                era = dasd_era_none;
-       else if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags))
-               era = dasd_era_fatal; /* don't recover this request */
        else if (irb->esw.esw0.erw.cons)
                era = device->discipline->examine_error(cqr, irb);
        else
@@ -1104,7 +1102,7 @@ __dasd_process_erp(struct dasd_device *device, struct dasd_ccw_req *cqr)
 /*
  * Process ccw request queue.
  */
-static inline void
+static void
 __dasd_process_ccw_queue(struct dasd_device * device,
                         struct list_head *final_queue)
 {
@@ -1127,7 +1125,9 @@ restart:
                                cqr->status = DASD_CQR_FAILED;
                                cqr->stopclk = get_clock();
                        } else {
-                               if (cqr->irb.esw.esw0.erw.cons) {
+                               if (cqr->irb.esw.esw0.erw.cons &&
+                                   test_bit(DASD_CQR_FLAGS_USE_ERP,
+                                            &cqr->flags)) {
                                        erp_fn = device->discipline->
                                                erp_action(cqr);
                                        erp_fn(cqr);
@@ -1181,7 +1181,7 @@ dasd_end_request_cb(struct dasd_ccw_req * cqr, void *data)
 /*
  * Fetch requests from the block device queue.
  */
-static inline void
+static void
 __dasd_process_blk_queue(struct dasd_device * device)
 {
        request_queue_t *queue;
@@ -1232,6 +1232,19 @@ __dasd_process_blk_queue(struct dasd_device * device)
                if (IS_ERR(cqr)) {
                        if (PTR_ERR(cqr) == -ENOMEM)
                                break;  /* terminate request queue loop */
+                       if (PTR_ERR(cqr) == -EAGAIN) {
+                               /*
+                                * The current request cannot be build right
+                                * now, we have to try later. If this request
+                                * is the head-of-queue we stop the device
+                                * for 1/2 second.
+                                */
+                               if (!list_empty(&device->ccw_queue))
+                                       break;
+                               device->stopped |= DASD_STOPPED_PENDING;
+                               dasd_set_timer(device, HZ/2);
+                               break;
+                       }
                        DBF_DEV_EVENT(DBF_ERR, device,
                                      "CCW creation failed (rc=%ld) "
                                      "on request %p",
@@ -1254,7 +1267,7 @@ __dasd_process_blk_queue(struct dasd_device * device)
  * Take a look at the first request on the ccw queue and check
  * if it reached its expire time. If so, terminate the IO.
  */
-static inline void
+static void
 __dasd_check_expire(struct dasd_device * device)
 {
        struct dasd_ccw_req *cqr;
@@ -1285,7 +1298,7 @@ __dasd_check_expire(struct dasd_device * device)
  * Take a look at the first request on the ccw queue and check
  * if it needs to be started.
  */
-static inline void
+static void
 __dasd_start_head(struct dasd_device * device)
 {
        struct dasd_ccw_req *cqr;
index 4d01040c2c63c0523cd49d5fee17fb483ff8520c..8b9d68f6e016f6f92c3d34a54aba4f6bc4a4e568 100644 (file)
@@ -170,7 +170,6 @@ dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb)
        /* log the erp chain if fatal error occurred */
        if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) {
                dasd_log_sense(cqr, irb);
-               dasd_log_ccw(cqr, 0, irb->scsw.cpa);
        }
 
        return era;
@@ -2640,7 +2639,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
 
        struct dasd_ccw_req *erp = NULL;
        struct dasd_device *device = cqr->device;
-       __u32 cpa = cqr->irb.scsw.cpa;
        struct dasd_ccw_req *temp_erp = NULL;
 
        if (device->features & DASD_FEATURE_ERPLOG) {
@@ -2706,9 +2704,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
                }
        }
 
-       if (erp->status == DASD_CQR_FAILED)
-               dasd_log_ccw(erp, 1, cpa);
-
        /* enqueue added ERP request */
        if (erp->status == DASD_CQR_FILLED) {
                erp->status = DASD_CQR_QUEUED;
index 5943266152f5ec899de2f5a8a98b435328ff8872..ed70852cc9154666a0bffeb95d813c2cbd762268 100644 (file)
@@ -136,7 +136,7 @@ __setup ("dasd=", dasd_call_setup);
 /*
  * Read a device busid/devno from a string.
  */
-static inline int
+static int
 dasd_busid(char **str, int *id0, int *id1, int *devno)
 {
        int val, old_style;
@@ -182,7 +182,7 @@ dasd_busid(char **str, int *id0, int *id1, int *devno)
  * only one: "ro" for read-only devices. The default feature set
  * is empty (value 0).
  */
-static inline int
+static int
 dasd_feature_list(char *str, char **endp)
 {
        int features, len, rc;
@@ -341,7 +341,7 @@ dasd_parse_range( char *parsestring ) {
        return ERR_PTR(-EINVAL);
 }
 
-static inline char *
+static char *
 dasd_parse_next_element( char *parsestring ) {
        char * residual_str;
        residual_str = dasd_parse_keyword(parsestring);
index 53db58a68617e618df4b8333ec0ba32f98d4ef45..ab782bb46ac1a13978d21def078eca1b60cec77c 100644 (file)
@@ -43,7 +43,7 @@ MODULE_LICENSE("GPL");
 #define DIAG_MAX_RETRIES       32
 #define DIAG_TIMEOUT           50 * HZ
 
-struct dasd_discipline dasd_diag_discipline;
+static struct dasd_discipline dasd_diag_discipline;
 
 struct dasd_diag_private {
        struct dasd_diag_characteristics rdc_data;
@@ -90,7 +90,7 @@ static inline int dia250(void *iob, int cmd)
  * block offset. On success, return zero and set end_block to contain the
  * number of blocks on the device minus the specified offset. Return non-zero
  * otherwise. */
-static __inline__ int
+static inline int
 mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
             blocknum_t offset, blocknum_t *end_block)
 {
@@ -117,7 +117,7 @@ mdsk_init_io(struct dasd_device *device, unsigned int blocksize,
 
 /* Remove block I/O environment for device. Return zero on success, non-zero
  * otherwise. */
-static __inline__ int
+static inline int
 mdsk_term_io(struct dasd_device * device)
 {
        struct dasd_diag_private *private;
@@ -576,7 +576,7 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req,
                    "dump sense not available for DIAG data");
 }
 
-struct dasd_discipline dasd_diag_discipline = {
+static struct dasd_discipline dasd_diag_discipline = {
        .owner = THIS_MODULE,
        .name = "DIAG",
        .ebcname = "DIAG",
index fdaa471e845fa78c73ff7a704bada1fb0f0b3ff7..cecab2274a6e861dfeb238336c15d4a2c9db2088 100644 (file)
@@ -134,44 +134,7 @@ ceil_quot(unsigned int d1, unsigned int d2)
        return (d1 + (d2 - 1)) / d2;
 }
 
-static inline int
-bytes_per_record(struct dasd_eckd_characteristics *rdc, int kl, int dl)
-{
-       unsigned int fl1, fl2, int1, int2;
-       int bpr;
-
-       switch (rdc->formula) {
-       case 0x01:
-               fl1 = round_up_multiple(ECKD_F2(rdc) + dl, ECKD_F1(rdc));
-               fl2 = round_up_multiple(kl ? ECKD_F2(rdc) + kl : 0,
-                                       ECKD_F1(rdc));
-               bpr = fl1 + fl2;
-               break;
-       case 0x02:
-               int1 = ceil_quot(dl + ECKD_F6(rdc), ECKD_F5(rdc) << 1);
-               int2 = ceil_quot(kl + ECKD_F6(rdc), ECKD_F5(rdc) << 1);
-               fl1 = round_up_multiple(ECKD_F1(rdc) * ECKD_F2(rdc) + dl +
-                                       ECKD_F6(rdc) + ECKD_F4(rdc) * int1,
-                                       ECKD_F1(rdc));
-               fl2 = round_up_multiple(ECKD_F1(rdc) * ECKD_F3(rdc) + kl +
-                                       ECKD_F6(rdc) + ECKD_F4(rdc) * int2,
-                                       ECKD_F1(rdc));
-               bpr = fl1 + fl2;
-               break;
-       default:
-               bpr = 0;
-               break;
-       }
-       return bpr;
-}
-
-static inline unsigned int
-bytes_per_track(struct dasd_eckd_characteristics *rdc)
-{
-       return *(unsigned int *) (rdc->byte_per_track) >> 8;
-}
-
-static inline unsigned int
+static unsigned int
 recs_per_track(struct dasd_eckd_characteristics * rdc,
               unsigned int kl, unsigned int dl)
 {
@@ -204,37 +167,39 @@ recs_per_track(struct dasd_eckd_characteristics * rdc,
        return 0;
 }
 
-static inline void
+static int
 check_XRC (struct ccw1         *de_ccw,
            struct DE_eckd_data *data,
            struct dasd_device  *device)
 {
         struct dasd_eckd_private *private;
+       int rc;
 
         private = (struct dasd_eckd_private *) device->private;
+       if (!private->rdc_data.facilities.XRC_supported)
+               return 0;
 
         /* switch on System Time Stamp - needed for XRC Support */
-        if (private->rdc_data.facilities.XRC_supported) {
-
-                data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid'   */
-                data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */
-
-                data->ep_sys_time = get_clock ();
-
-                de_ccw->count = sizeof (struct DE_eckd_data);
-               de_ccw->flags |= CCW_FLAG_SLI;
-        }
+       data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid'   */
+       data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */
 
-        return;
+       rc = get_sync_clock(&data->ep_sys_time);
+       /* Ignore return code if sync clock is switched off. */
+       if (rc == -ENOSYS || rc == -EACCES)
+               rc = 0;
 
-} /* end check_XRC */
+       de_ccw->count = sizeof (struct DE_eckd_data);
+       de_ccw->flags |= CCW_FLAG_SLI;
+       return rc;
+}
 
-static inline void
+static int
 define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
              int totrk, int cmd, struct dasd_device * device)
 {
        struct dasd_eckd_private *private;
        struct ch_t geo, beg, end;
+       int rc = 0;
 
        private = (struct dasd_eckd_private *) device->private;
 
@@ -263,12 +228,12 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
        case DASD_ECKD_CCW_WRITE_KD_MT:
                data->mask.perm = 0x02;
                data->attributes.operation = private->attrib.operation;
-                check_XRC (ccw, data, device);
+               rc = check_XRC (ccw, data, device);
                break;
        case DASD_ECKD_CCW_WRITE_CKD:
        case DASD_ECKD_CCW_WRITE_CKD_MT:
                data->attributes.operation = DASD_BYPASS_CACHE;
-                check_XRC (ccw, data, device);
+               rc = check_XRC (ccw, data, device);
                break;
        case DASD_ECKD_CCW_ERASE:
        case DASD_ECKD_CCW_WRITE_HOME_ADDRESS:
@@ -276,7 +241,7 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
                data->mask.perm = 0x3;
                data->mask.auth = 0x1;
                data->attributes.operation = DASD_BYPASS_CACHE;
-                check_XRC (ccw, data, device);
+               rc = check_XRC (ccw, data, device);
                break;
        default:
                DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd);
@@ -312,9 +277,10 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk,
        data->beg_ext.head = beg.head;
        data->end_ext.cyl = end.cyl;
        data->end_ext.head = end.head;
+       return rc;
 }
 
-static inline void
+static void
 locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk,
              int rec_on_trk, int no_rec, int cmd,
              struct dasd_device * device, int reclen)
@@ -548,7 +514,7 @@ dasd_eckd_read_conf(struct dasd_device *device)
 /*
  * Build CP for Perform Subsystem Function - SSC.
  */
-struct dasd_ccw_req *
+static struct dasd_ccw_req *
 dasd_eckd_build_psf_ssc(struct dasd_device *device)
 {
        struct dasd_ccw_req *cqr;
@@ -1200,7 +1166,12 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req)
                return cqr;
        ccw = cqr->cpaddr;
        /* First ccw is define extent. */
-       define_extent(ccw++, cqr->data, first_trk, last_trk, cmd, device);
+       if (define_extent(ccw++, cqr->data, first_trk,
+                         last_trk, cmd, device) == -EAGAIN) {
+               /* Clock not in sync and XRC is enabled. Try again later. */
+               dasd_sfree_request(cqr, device);
+               return ERR_PTR(-EAGAIN);
+       }
        /* Build locate_record+read/write/ccws. */
        idaws = (unsigned long *) (cqr->data + sizeof(struct DE_eckd_data));
        LO_data = (struct LO_eckd_data *) (idaws + cidaw);
@@ -1380,7 +1351,7 @@ dasd_eckd_release(struct dasd_device *device)
        cqr->device = device;
        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
        set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
-       cqr->retries = 0;
+       cqr->retries = 2;       /* set retry counter to enable basic ERP */
        cqr->expires = 2 * HZ;
        cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
@@ -1420,7 +1391,7 @@ dasd_eckd_reserve(struct dasd_device *device)
        cqr->device = device;
        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
        set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
-       cqr->retries = 0;
+       cqr->retries = 2;       /* set retry counter to enable basic ERP */
        cqr->expires = 2 * HZ;
        cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
@@ -1459,7 +1430,7 @@ dasd_eckd_steal_lock(struct dasd_device *device)
        cqr->device = device;
        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
        set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
-       cqr->retries = 0;
+       cqr->retries = 2;       /* set retry counter to enable basic ERP */
        cqr->expires = 2 * HZ;
        cqr->buildclk = get_clock();
        cqr->status = DASD_CQR_FILLED;
@@ -1609,7 +1580,7 @@ dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp)
  * Dump the range of CCWs into 'page' buffer
  * and return number of printed chars.
  */
-static inline int
+static int
 dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page)
 {
        int len, count;
index e0bf30ebb21521106229348d610f6e182dc1a656..6cedc914077e7c3f33e7385a5c84be73ba3c2e8a 100644 (file)
@@ -658,18 +658,24 @@ static struct file_operations dasd_eer_fops = {
        .owner          = THIS_MODULE,
 };
 
-static struct miscdevice dasd_eer_dev = {
-       .minor      = MISC_DYNAMIC_MINOR,
-       .name       = "dasd_eer",
-       .fops       = &dasd_eer_fops,
-};
+static struct miscdevice *dasd_eer_dev = NULL;
 
 int __init dasd_eer_init(void)
 {
        int rc;
 
-       rc = misc_register(&dasd_eer_dev);
+       dasd_eer_dev = kzalloc(sizeof(*dasd_eer_dev), GFP_KERNEL);
+       if (!dasd_eer_dev)
+               return -ENOMEM;
+
+       dasd_eer_dev->minor = MISC_DYNAMIC_MINOR;
+       dasd_eer_dev->name  = "dasd_eer";
+       dasd_eer_dev->fops  = &dasd_eer_fops;
+
+       rc = misc_register(dasd_eer_dev);
        if (rc) {
+               kfree(dasd_eer_dev);
+               dasd_eer_dev = NULL;
                MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not "
                       "register misc device");
                return rc;
@@ -680,5 +686,9 @@ int __init dasd_eer_init(void)
 
 void dasd_eer_exit(void)
 {
-       WARN_ON(misc_deregister(&dasd_eer_dev) != 0);
+       if (dasd_eer_dev) {
+               WARN_ON(misc_deregister(dasd_eer_dev) != 0);
+               kfree(dasd_eer_dev);
+               dasd_eer_dev = NULL;
+       }
 }
index 58a65097922bb430d3f8e6b224755596e71fb746..caa5d91420f827a20a5f6c2c69706ffac091c346 100644 (file)
@@ -152,25 +152,6 @@ dasd_default_erp_postaction(struct dasd_ccw_req * cqr)
 
 }                              /* end default_erp_postaction */
 
-/*
- * Print the hex dump of the memory used by a request. This includes
- * all error recovery ccws that have been chained in from of the
- * real request.
- */
-static inline void
-hex_dump_memory(struct dasd_device *device, void *data, int len)
-{
-       int *pint;
-
-       pint = (int *) data;
-       while (len > 0) {
-               DEV_MESSAGE(KERN_ERR, device, "%p: %08x %08x %08x %08x",
-                           pint, pint[0], pint[1], pint[2], pint[3]);
-               pint += 4;
-               len -= 16;
-       }
-}
-
 void
 dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb)
 {
@@ -182,69 +163,8 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb)
                device->discipline->dump_sense(device, cqr, irb);
 }
 
-void
-dasd_log_ccw(struct dasd_ccw_req * cqr, int caller, __u32 cpa)
-{
-       struct dasd_device *device;
-       struct dasd_ccw_req *lcqr;
-       struct ccw1 *ccw;
-       int cplength;
-
-       device = cqr->device;
-       /* log the channel program */
-       for (lcqr = cqr; lcqr != NULL; lcqr = lcqr->refers) {
-               DEV_MESSAGE(KERN_ERR, device,
-                           "(%s) ERP chain report for req: %p",
-                           caller == 0 ? "EXAMINE" : "ACTION", lcqr);
-               hex_dump_memory(device, lcqr, sizeof(struct dasd_ccw_req));
-
-               cplength = 1;
-               ccw = lcqr->cpaddr;
-               while (ccw++->flags & (CCW_FLAG_DC | CCW_FLAG_CC))
-                       cplength++;
-
-               if (cplength > 40) {    /* log only parts of the CP */
-                       DEV_MESSAGE(KERN_ERR, device, "%s",
-                                   "Start of channel program:");
-                       hex_dump_memory(device, lcqr->cpaddr,
-                                       40*sizeof(struct ccw1));
-
-                       DEV_MESSAGE(KERN_ERR, device, "%s",
-                                   "End of channel program:");
-                       hex_dump_memory(device, lcqr->cpaddr + cplength - 10,
-                                       10*sizeof(struct ccw1));
-               } else {        /* log the whole CP */
-                       DEV_MESSAGE(KERN_ERR, device, "%s",
-                                   "Channel program (complete):");
-                       hex_dump_memory(device, lcqr->cpaddr,
-                                       cplength*sizeof(struct ccw1));
-               }
-
-               if (lcqr != cqr)
-                       continue;
-
-               /*
-                * Log bytes arround failed CCW but only if we did
-                * not log the whole CP of the CCW is outside the
-                * logged CP.
-                */
-               if (cplength > 40 ||
-                   ((addr_t) cpa < (addr_t) lcqr->cpaddr &&
-                    (addr_t) cpa > (addr_t) (lcqr->cpaddr + cplength + 4))) {
-
-                       DEV_MESSAGE(KERN_ERR, device,
-                                   "Failed CCW (%p) (area):",
-                                   (void *) (long) cpa);
-                       hex_dump_memory(device, cqr->cpaddr - 10,
-                                       20*sizeof(struct ccw1));
-               }
-       }
-
-}                              /* end log_erp_chain */
-
 EXPORT_SYMBOL(dasd_default_erp_action);
 EXPORT_SYMBOL(dasd_default_erp_postaction);
 EXPORT_SYMBOL(dasd_alloc_erp_request);
 EXPORT_SYMBOL(dasd_free_erp_request);
 EXPORT_SYMBOL(dasd_log_sense);
-EXPORT_SYMBOL(dasd_log_ccw);
index b857fd5893fdc4d35586e929e3060a070aa5b4d5..be0909e39226ac88719b387a1e6c1d9201043971 100644 (file)
@@ -75,7 +75,7 @@ static struct ccw_driver dasd_fba_driver = {
        .notify      = dasd_generic_notify,
 };
 
-static inline void
+static void
 define_extent(struct ccw1 * ccw, struct DE_fba_data *data, int rw,
              int blksize, int beg, int nr)
 {
@@ -95,7 +95,7 @@ define_extent(struct ccw1 * ccw, struct DE_fba_data *data, int rw,
        data->ext_end = nr - 1;
 }
 
-static inline void
+static void
 locate_record(struct ccw1 * ccw, struct LO_fba_data *data, int rw,
              int block_nr, int block_ct)
 {
index d163632101d2da8ed3535092da67d9298e340ae4..47ba4462708de9583cadef43f4cd0995567e7878 100644 (file)
@@ -147,7 +147,7 @@ dasd_destroy_partitions(struct dasd_device * device)
         */
        memset(&bpart, 0, sizeof(struct blkpg_partition));
        memset(&barg, 0, sizeof(struct blkpg_ioctl_arg));
-       barg.data = (void __user *) &bpart;
+       barg.data = (void __force __user *) &bpart;
        barg.op = BLKPG_DEL_PARTITION;
        for (bpart.pno = device->gdp->minors - 1; bpart.pno > 0; bpart.pno--)
                ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg);
index fb725e3b08fe4b14b4f5d54b8bd8ea8791f086fa..a2cc69e11410ed0afc4353896acebec53bd0947e 100644 (file)
@@ -559,7 +559,6 @@ struct dasd_ccw_req *dasd_alloc_erp_request(char *, int, int,
                                            struct dasd_device *);
 void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *);
 void dasd_log_sense(struct dasd_ccw_req *, struct irb *);
-void dasd_log_ccw(struct dasd_ccw_req *, int, __u32);
 
 /* externals in dasd_3370_erp.c */
 dasd_era_t dasd_3370_erp_examine(struct dasd_ccw_req *, struct irb *);
index bfa010f6dab25275223d7c6fde5e6e753883fa73..8b7e11815d7044fa4ba1490cb2fe5859f4137126 100644 (file)
@@ -28,7 +28,7 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL;
 static struct proc_dir_entry *dasd_devices_entry = NULL;
 static struct proc_dir_entry *dasd_statistics_entry = NULL;
 
-static inline char *
+static char *
 dasd_get_user_string(const char __user *user_buf, size_t user_len)
 {
        char *buffer;
@@ -154,7 +154,7 @@ static struct file_operations dasd_devices_file_ops = {
        .release        = seq_release,
 };
 
-static inline int
+static int
 dasd_calc_metrics(char *page, char **start, off_t off,
                  int count, int *eof, int len)
 {
@@ -167,8 +167,8 @@ dasd_calc_metrics(char *page, char **start, off_t off,
        return len;
 }
 
-static inline char *
-dasd_statistics_array(char *str, int *array, int shift)
+static char *
+dasd_statistics_array(char *str, unsigned int *array, int shift)
 {
        int i;
 
index be9b05347b4f9b839bcc75e8a7b57f98e2ad3113..1340451ea408534423d50ec5cd5b37e9802b7a24 100644 (file)
@@ -102,7 +102,7 @@ dcssblk_release_segment(struct device *dev)
  * device needs to be enqueued before the semaphore is
  * freed.
  */
-static inline int
+static int
 dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info)
 {
        int minor, found;
@@ -230,7 +230,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
                                           SEGMENT_SHARED);
                if (rc < 0) {
                        BUG_ON(rc == -EINVAL);
-                       if (rc == -EIO || rc == -ENOENT)
+                       if (rc != -EAGAIN)
                                goto removeseg;
                } else {
                        dev_info->is_shared = 1;
@@ -253,7 +253,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch
                                           SEGMENT_EXCLUSIVE);
                if (rc < 0) {
                        BUG_ON(rc == -EINVAL);
-                       if (rc == -EIO || rc == -ENOENT)
+                       if (rc != -EAGAIN)
                                goto removeseg;
                } else {
                        dev_info->is_shared = 0;
index c3e97b4fc18605e96767110a90644fdc3a4e02ca..293e667b50f26463156cac3812c42f516c0edb66 100644 (file)
@@ -2,7 +2,8 @@
 # S/390 character devices
 #
 
-obj-y += ctrlchar.o keyboard.o defkeymap.o
+obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \
+        sclp_info.o
 
 obj-$(CONFIG_TN3270) += raw3270.o
 obj-$(CONFIG_TN3270_CONSOLE) += con3270.o
@@ -11,7 +12,6 @@ obj-$(CONFIG_TN3270_FS) += fs3270.o
 
 obj-$(CONFIG_TN3215) += con3215.o
 
-obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o sclp_quiesce.o
 obj-$(CONFIG_SCLP_TTY) += sclp_tty.o
 obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o
 obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o
index 25b5d7a6641796fc272b41428917146a2dcd3215..9a328f14a6418bba396cf9b61f40e702b139ba24 100644 (file)
@@ -1121,7 +1121,7 @@ static const struct tty_operations tty3215_ops = {
  * 3215 tty registration code called from tty_init().
  * Most kernel services (incl. kmalloc) are available at this poimt.
  */
-int __init
+static int __init
 tty3215_init(void)
 {
        struct tty_driver *driver;
index 7566be8906889036aab0056d777d789b46029a19..8e7f2d7633d6f48fe71f5cbf2d43132a4f5f6818 100644 (file)
@@ -69,8 +69,7 @@ static void con3270_update(struct con3270 *);
 /*
  * Setup timeout for a device. On timeout trigger an update.
  */
-void
-con3270_set_timer(struct con3270 *cp, int expires)
+static void con3270_set_timer(struct con3270 *cp, int expires)
 {
        if (expires == 0) {
                if (timer_pending(&cp->timer))
index 17027d918cf78e435821b3fe56f5ebb4d002f9ab..564baca01b7c001635f9b6e4495f07468358c6e9 100644 (file)
@@ -5,6 +5,8 @@
 #include <linux/types.h>
 #include <linux/keyboard.h>
 #include <linux/kd.h>
+#include <linux/kbd_kern.h>
+#include <linux/kbd_diacr.h>
 
 u_short plain_map[NR_KEYS] = {
        0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000,
index 0893d306ae8094d10f512fc19fa4b1d288c5040a..e1a746269c4ccd9b5da42397a7da08daeae5be31 100644 (file)
@@ -23,7 +23,7 @@
 #include "raw3270.h"
 #include "ctrlchar.h"
 
-struct raw3270_fn fs3270_fn;
+static struct raw3270_fn fs3270_fn;
 
 struct fs3270 {
        struct raw3270_view view;
@@ -401,7 +401,7 @@ fs3270_release(struct raw3270_view *view)
 }
 
 /* View to a 3270 device. Can be console, tty or fullscreen. */
-struct raw3270_fn fs3270_fn = {
+static struct raw3270_fn fs3270_fn = {
        .activate = fs3270_activate,
        .deactivate = fs3270_deactivate,
        .intv = (void *) fs3270_irq,
index 3e86fd1756e5dc5b43df29fb6c7fd480fd2160b4..f62f9a4e89504005f8d45fe0aa0e96df5d513645 100644 (file)
@@ -148,6 +148,7 @@ kbd_ascebc(struct kbd_data *kbd, unsigned char *ascebc)
        }
 }
 
+#if 0
 /*
  * Generate ebcdic -> ascii translation table from kbd_data.
  */
@@ -173,6 +174,7 @@ kbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc)
                }
        }
 }
+#endif
 
 /*
  * We have a combining character DIACR here, followed by the character CH.
index cdb24f528112d904295e97844600e214c8750256..9e451acc6491fa50c22bc1c5f09592568fa5c054 100644 (file)
@@ -67,8 +67,8 @@ static int monwrite_diag(struct monwrite_hdr *myhdr, char *buffer, int fcn)
        return -EINVAL;
 }
 
-static inline struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv,
-                                               struct monwrite_hdr *monhdr)
+static struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv,
+                                        struct monwrite_hdr *monhdr)
 {
        struct mon_buf *entry, *next;
 
index 7a84014f2037f49a6e558e2ef4b6feed86e0868d..8facd14adb7c168ab2d5c6137fd6eee63ffebbec 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 
-struct class *class3270;
+static struct class *class3270;
 
 /* The main 3270 data structure. */
 struct raw3270 {
@@ -86,7 +86,7 @@ DECLARE_WAIT_QUEUE_HEAD(raw3270_wait_queue);
 /*
  * Encode array for 12 bit 3270 addresses.
  */
-unsigned char raw3270_ebcgraf[64] =    {
+static unsigned char raw3270_ebcgraf[64] =     {
        0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
        0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
        0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
index 8a056df09d6b2dfd33885402103b8ee53be18bfd..f171de3b0b1172442e13752b176f021214dbbfd1 100644 (file)
@@ -59,7 +59,8 @@ static volatile enum sclp_init_state_t {
 /* Internal state: is a request active at the sclp? */
 static volatile enum sclp_running_state_t {
        sclp_running_state_idle,
-       sclp_running_state_running
+       sclp_running_state_running,
+       sclp_running_state_reset_pending
 } sclp_running_state = sclp_running_state_idle;
 
 /* Internal state: is a read request pending? */
@@ -88,15 +89,15 @@ static volatile enum sclp_mask_state_t {
 
 /* Timeout intervals in seconds.*/
 #define SCLP_BUSY_INTERVAL     10
-#define SCLP_RETRY_INTERVAL    15
+#define SCLP_RETRY_INTERVAL    30
 
 static void sclp_process_queue(void);
 static int sclp_init_mask(int calculate);
 static int sclp_init(void);
 
 /* Perform service call. Return 0 on success, non-zero otherwise. */
-static int
-service_call(sclp_cmdw_t command, void *sccb)
+int
+sclp_service_call(sclp_cmdw_t command, void *sccb)
 {
        int cc;
 
@@ -113,19 +114,17 @@ service_call(sclp_cmdw_t command, void *sccb)
        return 0;
 }
 
-/* Request timeout handler. Restart the request queue. If DATA is non-zero,
- * force restart of running request. */
+static inline void __sclp_make_read_req(void);
+
 static void
-sclp_request_timeout(unsigned long data)
+__sclp_queue_read_req(void)
 {
-       unsigned long flags;
-
-       if (data) {
-               spin_lock_irqsave(&sclp_lock, flags);
-               sclp_running_state = sclp_running_state_idle;
-               spin_unlock_irqrestore(&sclp_lock, flags);
+       if (sclp_reading_state == sclp_reading_state_idle) {
+               sclp_reading_state = sclp_reading_state_reading;
+               __sclp_make_read_req();
+               /* Add request to head of queue */
+               list_add(&sclp_read_req.list, &sclp_req_queue);
        }
-       sclp_process_queue();
 }
 
 /* Set up request retry timer. Called while sclp_lock is locked. */
@@ -140,6 +139,29 @@ __sclp_set_request_timer(unsigned long time, void (*function)(unsigned long),
        add_timer(&sclp_request_timer);
 }
 
+/* Request timeout handler. Restart the request queue. If DATA is non-zero,
+ * force restart of running request. */
+static void
+sclp_request_timeout(unsigned long data)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&sclp_lock, flags);
+       if (data) {
+               if (sclp_running_state == sclp_running_state_running) {
+                       /* Break running state and queue NOP read event request
+                        * to get a defined interface state. */
+                       __sclp_queue_read_req();
+                       sclp_running_state = sclp_running_state_idle;
+               }
+       } else {
+               __sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ,
+                                        sclp_request_timeout, 0);
+       }
+       spin_unlock_irqrestore(&sclp_lock, flags);
+       sclp_process_queue();
+}
+
 /* Try to start a request. Return zero if the request was successfully
  * started or if it will be started at a later time. Return non-zero otherwise.
  * Called while sclp_lock is locked. */
@@ -151,7 +173,7 @@ __sclp_start_request(struct sclp_req *req)
        if (sclp_running_state != sclp_running_state_idle)
                return 0;
        del_timer(&sclp_request_timer);
-       rc = service_call(req->command, req->sccb);
+       rc = sclp_service_call(req->command, req->sccb);
        req->start_count++;
 
        if (rc == 0) {
@@ -191,7 +213,15 @@ sclp_process_queue(void)
                rc = __sclp_start_request(req);
                if (rc == 0)
                        break;
-               /* Request failed. */
+               /* Request failed */
+               if (req->start_count > 1) {
+                       /* Cannot abort already submitted request - could still
+                        * be active at the SCLP */
+                       __sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ,
+                                                sclp_request_timeout, 0);
+                       break;
+               }
+               /* Post-processing for aborted request */
                list_del(&req->list);
                if (req->callback) {
                        spin_unlock_irqrestore(&sclp_lock, flags);
@@ -221,7 +251,8 @@ sclp_add_request(struct sclp_req *req)
        list_add_tail(&req->list, &sclp_req_queue);
        rc = 0;
        /* Start if request is first in list */
-       if (req->list.prev == &sclp_req_queue) {
+       if (sclp_running_state == sclp_running_state_idle &&
+           req->list.prev == &sclp_req_queue) {
                rc = __sclp_start_request(req);
                if (rc)
                        list_del(&req->list);
@@ -294,7 +325,7 @@ __sclp_make_read_req(void)
        sccb = (struct sccb_header *) sclp_read_sccb;
        clear_page(sccb);
        memset(&sclp_read_req, 0, sizeof(struct sclp_req));
-       sclp_read_req.command = SCLP_CMDW_READDATA;
+       sclp_read_req.command = SCLP_CMDW_READ_EVENT_DATA;
        sclp_read_req.status = SCLP_REQ_QUEUED;
        sclp_read_req.start_count = 0;
        sclp_read_req.callback = sclp_read_cb;
@@ -334,6 +365,8 @@ sclp_interrupt_handler(__u16 code)
        finished_sccb = S390_lowcore.ext_params & 0xfffffff8;
        evbuf_pending = S390_lowcore.ext_params & 0x3;
        if (finished_sccb) {
+               del_timer(&sclp_request_timer);
+               sclp_running_state = sclp_running_state_reset_pending;
                req = __sclp_find_req(finished_sccb);
                if (req) {
                        /* Request post-processing */
@@ -348,13 +381,8 @@ sclp_interrupt_handler(__u16 code)
                sclp_running_state = sclp_running_state_idle;
        }
        if (evbuf_pending && sclp_receive_mask != 0 &&
-           sclp_reading_state == sclp_reading_state_idle &&
-           sclp_activation_state == sclp_activation_state_active ) {
-               sclp_reading_state = sclp_reading_state_reading;
-               __sclp_make_read_req();
-               /* Add request to head of queue */
-               list_add(&sclp_read_req.list, &sclp_req_queue);
-       }
+           sclp_activation_state == sclp_activation_state_active)
+               __sclp_queue_read_req();
        spin_unlock(&sclp_lock);
        sclp_process_queue();
 }
@@ -374,6 +402,7 @@ sclp_sync_wait(void)
        unsigned long flags;
        unsigned long cr0, cr0_sync;
        u64 timeout;
+       int irq_context;
 
        /* We'll be disabling timer interrupts, so we need a custom timeout
         * mechanism */
@@ -386,7 +415,9 @@ sclp_sync_wait(void)
        }
        local_irq_save(flags);
        /* Prevent bottom half from executing once we force interrupts open */
-       local_bh_disable();
+       irq_context = in_interrupt();
+       if (!irq_context)
+               local_bh_disable();
        /* Enable service-signal interruption, disable timer interrupts */
        trace_hardirqs_on();
        __ctl_store(cr0, 0, 0);
@@ -402,19 +433,19 @@ sclp_sync_wait(void)
                    get_clock() > timeout &&
                    del_timer(&sclp_request_timer))
                        sclp_request_timer.function(sclp_request_timer.data);
-               barrier();
                cpu_relax();
        }
        local_irq_disable();
        __ctl_load(cr0, 0, 0);
-       _local_bh_enable();
+       if (!irq_context)
+               _local_bh_enable();
        local_irq_restore(flags);
 }
 
 EXPORT_SYMBOL(sclp_sync_wait);
 
 /* Dispatch changes in send and receive mask to registered listeners. */
-static inline void
+static void
 sclp_dispatch_state_change(void)
 {
        struct list_head *l;
@@ -597,7 +628,7 @@ __sclp_make_init_req(u32 receive_mask, u32 send_mask)
        sccb = (struct init_sccb *) sclp_init_sccb;
        clear_page(sccb);
        memset(&sclp_init_req, 0, sizeof(struct sclp_req));
-       sclp_init_req.command = SCLP_CMDW_WRITEMASK;
+       sclp_init_req.command = SCLP_CMDW_WRITE_EVENT_MASK;
        sclp_init_req.status = SCLP_REQ_FILLED;
        sclp_init_req.start_count = 0;
        sclp_init_req.callback = NULL;
@@ -800,7 +831,7 @@ sclp_check_interface(void)
        for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) {
                __sclp_make_init_req(0, 0);
                sccb = (struct init_sccb *) sclp_init_req.sccb;
-               rc = service_call(sclp_init_req.command, sccb);
+               rc = sclp_service_call(sclp_init_req.command, sccb);
                if (rc == -EIO)
                        break;
                sclp_init_req.status = SCLP_REQ_RUNNING;
index 2c71d6ee7b5b63ef2ab295e33830258f6fd383a7..7d29ab45a6ed7fb21b392a5d2cd785e1f1c7983a 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
+#include <asm/sclp.h>
 #include <asm/ebcdic.h>
 
 /* maximum number of pages concerning our own memory management */
 
 typedef unsigned int sclp_cmdw_t;
 
-#define SCLP_CMDW_READDATA     0x00770005
-#define SCLP_CMDW_WRITEDATA    0x00760005
-#define SCLP_CMDW_WRITEMASK    0x00780005
+#define SCLP_CMDW_READ_EVENT_DATA      0x00770005
+#define SCLP_CMDW_WRITE_EVENT_DATA     0x00760005
+#define SCLP_CMDW_WRITE_EVENT_MASK     0x00780005
+#define SCLP_CMDW_READ_SCP_INFO                0x00020001
+#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
 
 #define GDS_ID_MDSMU           0x1310
 #define GDS_ID_MDSRouteInfo    0x1311
@@ -66,13 +68,6 @@ typedef unsigned int sclp_cmdw_t;
 
 typedef u32 sccb_mask_t;       /* ATTENTION: assumes 32bit mask !!! */
 
-struct sccb_header {
-       u16     length;
-       u8      function_code;
-       u8      control_mask[3];
-       u16     response_code;
-} __attribute__((packed));
-
 struct gds_subvector {
        u8      length;
        u8      key;
@@ -131,6 +126,7 @@ void sclp_unregister(struct sclp_register *reg);
 int sclp_remove_processed(struct sccb_header *sccb);
 int sclp_deactivate(void);
 int sclp_reactivate(void);
+int sclp_service_call(sclp_cmdw_t command, void *sccb);
 
 /* useful inlines */
 
index 86864f641716045b4b9e234018962136c1a1095e..ead1043d788ec3338525f83ed9655a8fec5c9072 100644 (file)
@@ -66,7 +66,7 @@ sclp_conbuf_callback(struct sclp_buffer *buffer, int rc)
        } while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback));
 }
 
-static inline void
+static void
 sclp_conbuf_emit(void)
 {
        struct sclp_buffer* buffer;
index 4f873ae148b720e5e314c3755d4eea5d98714771..65aa2c85737fe433e32e231f6b1f7048604ff20c 100644 (file)
@@ -169,7 +169,7 @@ cpi_prepare_req(void)
        }
 
        /* prepare request data structure presented to SCLP driver */
-       req->command = SCLP_CMDW_WRITEDATA;
+       req->command = SCLP_CMDW_WRITE_EVENT_DATA;
        req->sccb = sccb;
        req->status = SCLP_REQ_FILLED;
        req->callback = cpi_callback;
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c
new file mode 100644 (file)
index 0000000..7bcbe64
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  drivers/s390/char/sclp_info.c
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <asm/sclp.h>
+#include "sclp.h"
+
+struct sclp_readinfo_sccb s390_readinfo_sccb;
+
+void __init sclp_readinfo_early(void)
+{
+       sclp_cmdw_t command;
+       struct sccb_header *sccb;
+       int ret;
+
+       __ctl_set_bit(0, 9); /* enable service signal subclass mask */
+
+       sccb = &s390_readinfo_sccb.header;
+       command = SCLP_CMDW_READ_SCP_INFO_FORCED;
+       while (1) {
+               u16 response;
+
+               memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb));
+               sccb->length = sizeof(s390_readinfo_sccb);
+               sccb->control_mask[2] = 0x80;
+
+               ret = sclp_service_call(command, &s390_readinfo_sccb);
+
+               if (ret == -EIO)
+                       goto out;
+               if (ret == -EBUSY)
+                       continue;
+
+               __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT |
+                               PSW_MASK_WAIT | PSW_DEFAULT_KEY);
+               local_irq_disable();
+               barrier();
+
+               response = sccb->response_code;
+
+               if (response == 0x10)
+                       break;
+
+               if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO)
+                       break;
+
+               command = SCLP_CMDW_READ_SCP_INFO;
+       }
+out:
+       __ctl_clear_bit(0, 9); /* disable service signal subclass mask */
+}
index 0c92d3909cca411f6fac68d8ff758d22457a2f48..2486783ea58e667a012a4444d24ae53d79c33935 100644 (file)
@@ -460,7 +460,7 @@ sclp_emit_buffer(struct sclp_buffer *buffer,
                sccb->msg_buf.header.type = EvTyp_PMsgCmd;
        else
                return -ENOSYS;
-       buffer->request.command = SCLP_CMDW_WRITEDATA;
+       buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA;
        buffer->request.status = SCLP_REQ_FILLED;
        buffer->request.callback = sclp_writedata_callback;
        buffer->request.callback_data = buffer;
index 2d173e5c8a098514d5f23f136bbe775122bc920e..90536f60bf502f0410c13607d0b0555c494ae374 100644 (file)
@@ -721,7 +721,7 @@ static const struct tty_operations sclp_ops = {
        .ioctl = sclp_tty_ioctl,
 };
 
-int __init
+static int __init
 sclp_tty_init(void)
 {
        struct tty_driver *driver;
index 723bf4191bfe2adb009c55d59797dfd98891f882..544f137d70d7e184a04172330ddae4ce1d6561d6 100644 (file)
@@ -207,7 +207,7 @@ __sclp_vt220_emit(struct sclp_vt220_request *request)
                request->sclp_req.status = SCLP_REQ_FAILED;
                return -EIO;
        }
-       request->sclp_req.command = SCLP_CMDW_WRITEDATA;
+       request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA;
        request->sclp_req.status = SCLP_REQ_FILLED;
        request->sclp_req.callback = sclp_vt220_callback;
        request->sclp_req.callback_data = (void *) request;
@@ -669,7 +669,7 @@ static const struct tty_operations sclp_vt220_ops = {
 /*
  * Register driver with SCLP and Linux and initialize internal tty structures.
  */
-int __init
+static int __init
 sclp_vt220_tty_init(void)
 {
        struct tty_driver *driver;
index c9f1c4c8bb134be37e6542fe1c27b1321075bcb5..bb4ff537729deb53fbcb629b7e47278643fd406a 100644 (file)
@@ -3,7 +3,7 @@
  *    tape device driver for 3480/3490E/3590 tapes.
  *
  *  S390 and zSeries version
- *    Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *              Tuan Ngo-Anh <ngoanh@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -99,7 +99,11 @@ enum tape_op {
        TO_DIS,         /* Tape display */
        TO_ASSIGN,      /* Assign tape to channel path */
        TO_UNASSIGN,    /* Unassign tape from channel path */
-       TO_SIZE         /* #entries in tape_op_t */
+       TO_CRYPT_ON,    /* Enable encrpytion */
+       TO_CRYPT_OFF,   /* Disable encrpytion */
+       TO_KEKL_SET,    /* Set KEK label */
+       TO_KEKL_QUERY,  /* Query KEK label */
+       TO_SIZE,        /* #entries in tape_op_t */
 };
 
 /* Forward declaration */
@@ -112,6 +116,7 @@ enum tape_request_status {
        TAPE_REQUEST_IN_IO,     /* request is currently in IO */
        TAPE_REQUEST_DONE,      /* request is completed. */
        TAPE_REQUEST_CANCEL,    /* request should be canceled. */
+       TAPE_REQUEST_LONG_BUSY, /* request has to be restarted after long busy */
 };
 
 /* Tape CCW request */
@@ -164,10 +169,11 @@ struct tape_discipline {
  * The discipline irq function either returns an error code (<0) which
  * means that the request has failed with an error or one of the following:
  */
-#define TAPE_IO_SUCCESS 0      /* request successful */
-#define TAPE_IO_PENDING 1      /* request still running */
-#define TAPE_IO_RETRY  2       /* retry to current request */
-#define TAPE_IO_STOP   3       /* stop the running request */
+#define TAPE_IO_SUCCESS                0       /* request successful */
+#define TAPE_IO_PENDING                1       /* request still running */
+#define TAPE_IO_RETRY          2       /* retry to current request */
+#define TAPE_IO_STOP           3       /* stop the running request */
+#define TAPE_IO_LONG_BUSY      4       /* delay the running request */
 
 /* Char Frontend Data */
 struct tape_char_data {
@@ -242,6 +248,10 @@ struct tape_device {
 
        /* Function to start or stop the next request later. */
        struct delayed_work             tape_dnr;
+
+       /* Timer for long busy */
+       struct timer_list               lb_timeout;
+
 };
 
 /* Externals from tape_core.c */
index 9df912f63188462f08990294c9e2366c80a2b632..50f5edab83d7fcc79672ceff0c75cc701fd4b7a0 100644 (file)
@@ -2,7 +2,7 @@
  *  drivers/s390/char/tape_3590.c
  *    tape device discipline for 3590 tapes.
  *
- *    Copyright (C) IBM Corp. 2001,2006
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Stefan Bader <shbader@de.ibm.com>
  *              Michael Holzheu <holzheu@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/bio.h>
+#include <asm/ebcdic.h>
 
 #define TAPE_DBF_AREA  tape_3590_dbf
 
@@ -30,7 +31,7 @@ EXPORT_SYMBOL(TAPE_DBF_AREA);
  * - Read Device (buffered) log: BRA
  * - Read Library log:          BRA
  * - Swap Devices:              BRA
- * - Long Busy:                         BRA
+ * - Long Busy:                         implemented
  * - Special Intercept:                 BRA
  * - Read Alternate:            implemented
  *******************************************************************/
@@ -94,6 +95,332 @@ static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = {
        [0xae] = "Subsystem environmental alert",
 };
 
+static int crypt_supported(struct tape_device *device)
+{
+       return TAPE390_CRYPT_SUPPORTED(TAPE_3590_CRYPT_INFO(device));
+}
+
+static int crypt_enabled(struct tape_device *device)
+{
+       return TAPE390_CRYPT_ON(TAPE_3590_CRYPT_INFO(device));
+}
+
+static void ext_to_int_kekl(struct tape390_kekl *in,
+                           struct tape3592_kekl *out)
+{
+       int i;
+
+       memset(out, 0, sizeof(*out));
+       if (in->type == TAPE390_KEKL_TYPE_HASH)
+               out->flags |= 0x40;
+       if (in->type_on_tape == TAPE390_KEKL_TYPE_HASH)
+               out->flags |= 0x80;
+       strncpy(out->label, in->label, 64);
+       for (i = strlen(in->label); i < sizeof(out->label); i++)
+               out->label[i] = ' ';
+       ASCEBC(out->label, sizeof(out->label));
+}
+
+static void int_to_ext_kekl(struct tape3592_kekl *in,
+                           struct tape390_kekl *out)
+{
+       memset(out, 0, sizeof(*out));
+       if(in->flags & 0x40)
+               out->type = TAPE390_KEKL_TYPE_HASH;
+       else
+               out->type = TAPE390_KEKL_TYPE_LABEL;
+       if(in->flags & 0x80)
+               out->type_on_tape = TAPE390_KEKL_TYPE_HASH;
+       else
+               out->type_on_tape = TAPE390_KEKL_TYPE_LABEL;
+       memcpy(out->label, in->label, sizeof(in->label));
+       EBCASC(out->label, sizeof(in->label));
+       strstrip(out->label);
+}
+
+static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in,
+                                struct tape390_kekl_pair *out)
+{
+       if (in->count == 0) {
+               out->kekl[0].type = TAPE390_KEKL_TYPE_NONE;
+               out->kekl[0].type_on_tape = TAPE390_KEKL_TYPE_NONE;
+               out->kekl[1].type = TAPE390_KEKL_TYPE_NONE;
+               out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE;
+       } else if (in->count == 1) {
+               int_to_ext_kekl(&in->kekl[0], &out->kekl[0]);
+               out->kekl[1].type = TAPE390_KEKL_TYPE_NONE;
+               out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE;
+       } else if (in->count == 2) {
+               int_to_ext_kekl(&in->kekl[0], &out->kekl[0]);
+               int_to_ext_kekl(&in->kekl[1], &out->kekl[1]);
+       } else {
+               printk("Invalid KEKL number: %d\n", in->count);
+               BUG();
+       }
+}
+
+static int check_ext_kekl(struct tape390_kekl *kekl)
+{
+       if (kekl->type == TAPE390_KEKL_TYPE_NONE)
+               goto invalid;
+       if (kekl->type > TAPE390_KEKL_TYPE_HASH)
+               goto invalid;
+       if (kekl->type_on_tape == TAPE390_KEKL_TYPE_NONE)
+               goto invalid;
+       if (kekl->type_on_tape > TAPE390_KEKL_TYPE_HASH)
+               goto invalid;
+       if ((kekl->type == TAPE390_KEKL_TYPE_HASH) &&
+           (kekl->type_on_tape == TAPE390_KEKL_TYPE_LABEL))
+               goto invalid;
+
+       return 0;
+invalid:
+       return -EINVAL;
+}
+
+static int check_ext_kekl_pair(struct tape390_kekl_pair *kekls)
+{
+       if (check_ext_kekl(&kekls->kekl[0]))
+               goto invalid;
+       if (check_ext_kekl(&kekls->kekl[1]))
+               goto invalid;
+
+       return 0;
+invalid:
+       return -EINVAL;
+}
+
+/*
+ * Query KEKLs
+ */
+static int tape_3592_kekl_query(struct tape_device *device,
+                               struct tape390_kekl_pair *ext_kekls)
+{
+       struct tape_request *request;
+       struct tape3592_kekl_query_order *order;
+       struct tape3592_kekl_query_data *int_kekls;
+       int rc;
+
+       DBF_EVENT(6, "tape3592_kekl_query\n");
+       int_kekls = kmalloc(sizeof(*int_kekls), GFP_KERNEL|GFP_DMA);
+       if (!int_kekls)
+               return -ENOMEM;
+       request = tape_alloc_request(2, sizeof(*order));
+       if (IS_ERR(request)) {
+               rc = PTR_ERR(request);
+               goto fail_malloc;
+       }
+       order = request->cpdata;
+       memset(order,0,sizeof(*order));
+       order->code = 0xe2;
+       order->max_count = 2;
+       request->op = TO_KEKL_QUERY;
+       tape_ccw_cc(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);
+       tape_ccw_end(request->cpaddr + 1, READ_SS_DATA, sizeof(*int_kekls),
+                    int_kekls);
+       rc = tape_do_io(device, request);
+       if (rc)
+               goto fail_request;
+       int_to_ext_kekl_pair(&int_kekls->kekls, ext_kekls);
+
+       rc = 0;
+fail_request:
+       tape_free_request(request);
+fail_malloc:
+       kfree(int_kekls);
+       return rc;
+}
+
+/*
+ * IOCTL: Query KEKLs
+ */
+static int tape_3592_ioctl_kekl_query(struct tape_device *device,
+                                     unsigned long arg)
+{
+       int rc;
+       struct tape390_kekl_pair *ext_kekls;
+
+       DBF_EVENT(6, "tape_3592_ioctl_kekl_query\n");
+       if (!crypt_supported(device))
+               return -ENOSYS;
+       if (!crypt_enabled(device))
+               return -EUNATCH;
+       ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL);
+       if (!ext_kekls)
+               return -ENOMEM;
+       rc = tape_3592_kekl_query(device, ext_kekls);
+       if (rc != 0)
+               goto fail;
+       if (copy_to_user((char __user *) arg, ext_kekls, sizeof(*ext_kekls))) {
+               rc = -EFAULT;
+               goto fail;
+       }
+       rc = 0;
+fail:
+       kfree(ext_kekls);
+       return rc;
+}
+
+static int tape_3590_mttell(struct tape_device *device, int mt_count);
+
+/*
+ * Set KEKLs
+ */
+static int tape_3592_kekl_set(struct tape_device *device,
+                             struct tape390_kekl_pair *ext_kekls)
+{
+       struct tape_request *request;
+       struct tape3592_kekl_set_order *order;
+
+       DBF_EVENT(6, "tape3592_kekl_set\n");
+       if (check_ext_kekl_pair(ext_kekls)) {
+               DBF_EVENT(6, "invalid kekls\n");
+               return -EINVAL;
+       }
+       if (tape_3590_mttell(device, 0) != 0)
+               return -EBADSLT;
+       request = tape_alloc_request(1, sizeof(*order));
+       if (IS_ERR(request))
+               return PTR_ERR(request);
+       order = request->cpdata;
+       memset(order, 0, sizeof(*order));
+       order->code = 0xe3;
+       order->kekls.count = 2;
+       ext_to_int_kekl(&ext_kekls->kekl[0], &order->kekls.kekl[0]);
+       ext_to_int_kekl(&ext_kekls->kekl[1], &order->kekls.kekl[1]);
+       request->op = TO_KEKL_SET;
+       tape_ccw_end(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order);
+
+       return tape_do_io_free(device, request);
+}
+
+/*
+ * IOCTL: Set KEKLs
+ */
+static int tape_3592_ioctl_kekl_set(struct tape_device *device,
+                                   unsigned long arg)
+{
+       int rc;
+       struct tape390_kekl_pair *ext_kekls;
+
+       DBF_EVENT(6, "tape_3592_ioctl_kekl_set\n");
+       if (!crypt_supported(device))
+               return -ENOSYS;
+       if (!crypt_enabled(device))
+               return -EUNATCH;
+       ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL);
+       if (!ext_kekls)
+               return -ENOMEM;
+       if (copy_from_user(ext_kekls, (char __user *)arg, sizeof(*ext_kekls))) {
+               rc = -EFAULT;
+               goto out;
+       }
+       rc = tape_3592_kekl_set(device, ext_kekls);
+out:
+       kfree(ext_kekls);
+       return rc;
+}
+
+/*
+ * Enable encryption
+ */
+static int tape_3592_enable_crypt(struct tape_device *device)
+{
+       struct tape_request *request;
+       char *data;
+
+       DBF_EVENT(6, "tape_3592_enable_crypt\n");
+       if (!crypt_supported(device))
+               return -ENOSYS;
+       request = tape_alloc_request(2, 72);
+       if (IS_ERR(request))
+               return PTR_ERR(request);
+       data = request->cpdata;
+       memset(data,0,72);
+
+       data[0]       = 0x05;
+       data[36 + 0]  = 0x03;
+       data[36 + 1]  = 0x03;
+       data[36 + 4]  = 0x40;
+       data[36 + 6]  = 0x01;
+       data[36 + 14] = 0x2f;
+       data[36 + 18] = 0xc3;
+       data[36 + 35] = 0x72;
+       request->op = TO_CRYPT_ON;
+       tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
+       tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
+       return tape_do_io_free(device, request);
+}
+
+/*
+ * Disable encryption
+ */
+static int tape_3592_disable_crypt(struct tape_device *device)
+{
+       struct tape_request *request;
+       char *data;
+
+       DBF_EVENT(6, "tape_3592_disable_crypt\n");
+       if (!crypt_supported(device))
+               return -ENOSYS;
+       request = tape_alloc_request(2, 72);
+       if (IS_ERR(request))
+               return PTR_ERR(request);
+       data = request->cpdata;
+       memset(data,0,72);
+
+       data[0]       = 0x05;
+       data[36 + 0]  = 0x03;
+       data[36 + 1]  = 0x03;
+       data[36 + 35] = 0x32;
+
+       request->op = TO_CRYPT_OFF;
+       tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data);
+       tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36);
+
+       return tape_do_io_free(device, request);
+}
+
+/*
+ * IOCTL: Set encryption status
+ */
+static int tape_3592_ioctl_crypt_set(struct tape_device *device,
+                                    unsigned long arg)
+{
+       struct tape390_crypt_info info;
+
+       DBF_EVENT(6, "tape_3592_ioctl_crypt_set\n");
+       if (!crypt_supported(device))
+               return -ENOSYS;
+       if (copy_from_user(&info, (char __user *)arg, sizeof(info)))
+               return -EFAULT;
+       if (info.status & ~TAPE390_CRYPT_ON_MASK)
+               return -EINVAL;
+       if (info.status & TAPE390_CRYPT_ON_MASK)
+               return tape_3592_enable_crypt(device);
+       else
+               return tape_3592_disable_crypt(device);
+}
+
+static int tape_3590_sense_medium(struct tape_device *device);
+
+/*
+ * IOCTL: Query enryption status
+ */
+static int tape_3592_ioctl_crypt_query(struct tape_device *device,
+                                      unsigned long arg)
+{
+       DBF_EVENT(6, "tape_3592_ioctl_crypt_query\n");
+       if (!crypt_supported(device))
+               return -ENOSYS;
+       tape_3590_sense_medium(device);
+       if (copy_to_user((char __user *) arg, &TAPE_3590_CRYPT_INFO(device),
+               sizeof(TAPE_3590_CRYPT_INFO(device))))
+               return -EFAULT;
+       else
+               return 0;
+}
+
 /*
  * 3590 IOCTL Overload
  */
@@ -109,6 +436,14 @@ tape_3590_ioctl(struct tape_device *device, unsigned int cmd, unsigned long arg)
 
                return tape_std_display(device, &disp);
        }
+       case TAPE390_KEKL_SET:
+               return tape_3592_ioctl_kekl_set(device, arg);
+       case TAPE390_KEKL_QUERY:
+               return tape_3592_ioctl_kekl_query(device, arg);
+       case TAPE390_CRYPT_SET:
+               return tape_3592_ioctl_crypt_set(device, arg);
+       case TAPE390_CRYPT_QUERY:
+               return tape_3592_ioctl_crypt_query(device, arg);
        default:
                return -EINVAL; /* no additional ioctls */
        }
@@ -248,6 +583,12 @@ tape_3590_work_handler(struct work_struct *work)
        case TO_READ_ATTMSG:
                tape_3590_read_attmsg(p->device);
                break;
+       case TO_CRYPT_ON:
+               tape_3592_enable_crypt(p->device);
+               break;
+       case TO_CRYPT_OFF:
+               tape_3592_disable_crypt(p->device);
+               break;
        default:
                DBF_EVENT(3, "T3590: work handler undefined for "
                          "operation 0x%02x\n", p->op);
@@ -365,6 +706,33 @@ tape_3590_check_locate(struct tape_device *device, struct tape_request *request)
 }
 #endif
 
+static void tape_3590_med_state_set(struct tape_device *device,
+                                   struct tape_3590_med_sense *sense)
+{
+       struct tape390_crypt_info *c_info;
+
+       c_info = &TAPE_3590_CRYPT_INFO(device);
+
+       if (sense->masst == MSENSE_UNASSOCIATED) {
+               tape_med_state_set(device, MS_UNLOADED);
+               TAPE_3590_CRYPT_INFO(device).medium_status = 0;
+               return;
+       }
+       if (sense->masst != MSENSE_ASSOCIATED_MOUNT) {
+               PRINT_ERR("Unknown medium state: %x\n", sense->masst);
+               return;
+       }
+       tape_med_state_set(device, MS_LOADED);
+       c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK;
+       if (sense->flags & MSENSE_CRYPT_MASK) {
+               PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags);
+               c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK;
+       } else  {
+               DBF_EVENT(6, "Medium is not encrypted %04x\n", sense->flags);
+               c_info->medium_status &= ~TAPE390_MEDIUM_ENCRYPTED_MASK;
+       }
+}
+
 /*
  * The done handler is called at device/channel end and wakes up the sleeping
  * process
@@ -372,9 +740,10 @@ tape_3590_check_locate(struct tape_device *device, struct tape_request *request)
 static int
 tape_3590_done(struct tape_device *device, struct tape_request *request)
 {
-       struct tape_3590_med_sense *sense;
+       struct tape_3590_disc_data *disc_data;
 
        DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]);
+       disc_data = device->discdata;
 
        switch (request->op) {
        case TO_BSB:
@@ -394,13 +763,20 @@ tape_3590_done(struct tape_device *device, struct tape_request *request)
                break;
        case TO_RUN:
                tape_med_state_set(device, MS_UNLOADED);
+               tape_3590_schedule_work(device, TO_CRYPT_OFF);
                break;
        case TO_MSEN:
-               sense = (struct tape_3590_med_sense *) request->cpdata;
-               if (sense->masst == MSENSE_UNASSOCIATED)
-                       tape_med_state_set(device, MS_UNLOADED);
-               if (sense->masst == MSENSE_ASSOCIATED_MOUNT)
-                       tape_med_state_set(device, MS_LOADED);
+               tape_3590_med_state_set(device, request->cpdata);
+               break;
+       case TO_CRYPT_ON:
+               TAPE_3590_CRYPT_INFO(device).status
+                       |= TAPE390_CRYPT_ON_MASK;
+               *(device->modeset_byte) |= 0x03;
+               break;
+       case TO_CRYPT_OFF:
+               TAPE_3590_CRYPT_INFO(device).status
+                       &= ~TAPE390_CRYPT_ON_MASK;
+               *(device->modeset_byte) &= ~0x03;
                break;
        case TO_RBI:    /* RBI seems to succeed even without medium loaded. */
        case TO_NOP:    /* Same to NOP. */
@@ -409,8 +785,9 @@ tape_3590_done(struct tape_device *device, struct tape_request *request)
        case TO_DIS:
        case TO_ASSIGN:
        case TO_UNASSIGN:
-               break;
        case TO_SIZE:
+       case TO_KEKL_SET:
+       case TO_KEKL_QUERY:
                break;
        }
        return TAPE_IO_SUCCESS;
@@ -540,10 +917,8 @@ static int
 tape_3590_erp_long_busy(struct tape_device *device,
                        struct tape_request *request, struct irb *irb)
 {
-       /* FIXME: how about WAITING for a minute ? */
-       PRINT_WARN("(%s): Device is busy! Please wait a minute!\n",
-                  device->cdev->dev.bus_id);
-       return tape_3590_erp_basic(device, request, irb, -EBUSY);
+       DBF_EVENT(6, "Device is busy\n");
+       return TAPE_IO_LONG_BUSY;
 }
 
 /*
@@ -951,6 +1326,34 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb)
                   device->cdev->dev.bus_id, sense->mc);
 }
 
+static int tape_3590_crypt_error(struct tape_device *device,
+                                struct tape_request *request, struct irb *irb)
+{
+       u8 cu_rc, ekm_rc1;
+       u16 ekm_rc2;
+       u32 drv_rc;
+       char *bus_id, *sense;
+
+       sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data;
+       bus_id = device->cdev->dev.bus_id;
+       cu_rc = sense[0];
+       drv_rc = *((u32*) &sense[5]) & 0xffffff;
+       ekm_rc1 = sense[9];
+       ekm_rc2 = *((u16*) &sense[10]);
+       if ((cu_rc == 0) && (ekm_rc2 == 0xee31))
+               /* key not defined on EKM */
+               return tape_3590_erp_basic(device, request, irb, -EKEYREJECTED);
+       if ((cu_rc == 1) || (cu_rc == 2))
+               /* No connection to EKM */
+               return tape_3590_erp_basic(device, request, irb, -ENOTCONN);
+
+       PRINT_ERR("(%s): Unable to get encryption key from EKM\n", bus_id);
+       PRINT_ERR("(%s): CU=%02X DRIVE=%06X EKM=%02X:%04X\n", bus_id, cu_rc,
+               drv_rc, ekm_rc1, ekm_rc2);
+
+       return tape_3590_erp_basic(device, request, irb, -ENOKEY);
+}
+
 /*
  *  3590 error Recovery routine:
  *  If possible, it tries to recover from the error. If this is not possible,
@@ -979,6 +1382,8 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
 
        sense = (struct tape_3590_sense *) irb->ecw;
 
+       DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc);
+
        /*
         * First check all RC-QRCs where we want to do something special
         *   - "break":     basic error recovery is done
@@ -999,6 +1404,8 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
        case 0x2231:
                tape_3590_print_era_msg(device, irb);
                return tape_3590_erp_special_interrupt(device, request, irb);
+       case 0x2240:
+               return tape_3590_crypt_error(device, request, irb);
 
        case 0x3010:
                DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n",
@@ -1020,6 +1427,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
                DBF_EVENT(2, "(%08x): Rewind Unload complete\n",
                          device->cdev_id);
                tape_med_state_set(device, MS_UNLOADED);
+               tape_3590_schedule_work(device, TO_CRYPT_OFF);
                return tape_3590_erp_basic(device, request, irb, 0);
 
        case 0x4010:
@@ -1030,9 +1438,15 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
                PRINT_WARN("(%s): Tape operation when medium not loaded\n",
                           device->cdev->dev.bus_id);
                tape_med_state_set(device, MS_UNLOADED);
+               tape_3590_schedule_work(device, TO_CRYPT_OFF);
                return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
        case 0x4012:            /* Device Long Busy */
+               /* XXX: Also use long busy handling here? */
+               DBF_EVENT(6, "(%08x): LONG BUSY\n", device->cdev_id);
                tape_3590_print_era_msg(device, irb);
+               return tape_3590_erp_basic(device, request, irb, -EBUSY);
+       case 0x4014:
+               DBF_EVENT(6, "(%08x): Crypto LONG BUSY\n", device->cdev_id);
                return tape_3590_erp_long_busy(device, request, irb);
 
        case 0x5010:
@@ -1064,6 +1478,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request,
        case 0x5120:
        case 0x1120:
                tape_med_state_set(device, MS_UNLOADED);
+               tape_3590_schedule_work(device, TO_CRYPT_OFF);
                return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM);
 
        case 0x6020:
@@ -1142,21 +1557,47 @@ tape_3590_setup_device(struct tape_device *device)
 {
        int rc;
        struct tape_3590_disc_data *data;
+       char *rdc_data;
 
        DBF_EVENT(6, "3590 device setup\n");
-       data = kmalloc(sizeof(struct tape_3590_disc_data),
-                      GFP_KERNEL | GFP_DMA);
+       data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA);
        if (data == NULL)
                return -ENOMEM;
        data->read_back_op = READ_PREVIOUS;
        device->discdata = data;
 
-       if ((rc = tape_std_assign(device)) == 0) {
-               /* Try to find out if medium is loaded */
-               if ((rc = tape_3590_sense_medium(device)) != 0)
-                       DBF_LH(3, "3590 medium sense returned %d\n", rc);
+       rdc_data = kmalloc(64, GFP_KERNEL | GFP_DMA);
+       if (!rdc_data) {
+               rc = -ENOMEM;
+               goto fail_kmalloc;
+       }
+       rc = read_dev_chars(device->cdev, (void**)&rdc_data, 64);
+       if (rc) {
+               DBF_LH(3, "Read device characteristics failed!\n");
+               goto fail_kmalloc;
+       }
+       rc = tape_std_assign(device);
+       if (rc)
+               goto fail_rdc_data;
+       if (rdc_data[31] == 0x13) {
+               PRINT_INFO("Device has crypto support\n");
+               data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK;
+               tape_3592_disable_crypt(device);
+       } else {
+               DBF_EVENT(6, "Device has NO crypto support\n");
        }
+       /* Try to find out if medium is loaded */
+       rc = tape_3590_sense_medium(device);
+       if (rc) {
+               DBF_LH(3, "3590 medium sense returned %d\n", rc);
+               goto fail_rdc_data;
+       }
+       return 0;
 
+fail_rdc_data:
+       kfree(rdc_data);
+fail_kmalloc:
+       kfree(data);
        return rc;
 }
 
index cf274b9445a6fa0f3a079ddf1395426f518afaed..aa5138807af1d07801d99183e766e08fefda9104 100644 (file)
@@ -2,7 +2,7 @@
  *  drivers/s390/char/tape_3590.h
  *    tape device discipline for 3590 tapes.
  *
- *    Copyright (C) IBM Corp. 2001,2006
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Stefan Bader <shbader@de.ibm.com>
  *              Michael Holzheu <holzheu@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
 #define MSENSE_UNASSOCIATED     0x00
 #define MSENSE_ASSOCIATED_MOUNT         0x01
 #define MSENSE_ASSOCIATED_UMOUNT 0x02
+#define MSENSE_CRYPT_MASK       0x00000010
 
 #define TAPE_3590_MAX_MSG       0xb0
 
 /* Datatypes */
 
 struct tape_3590_disc_data {
-       unsigned char modeset_byte;
+       struct tape390_crypt_info crypt_info;
        int read_back_op;
 };
 
+#define TAPE_3590_CRYPT_INFO(device) \
+       ((struct tape_3590_disc_data*)(device->discdata))->crypt_info
+#define TAPE_3590_READ_BACK_OP(device) \
+       ((struct tape_3590_disc_data*)(device->discdata))->read_back_op
+
 struct tape_3590_sense {
 
        unsigned int command_rej:1;
@@ -118,7 +124,48 @@ struct tape_3590_sense {
 struct tape_3590_med_sense {
        unsigned int macst:4;
        unsigned int masst:4;
-       char pad[127];
+       char pad1[7];
+       unsigned int flags;
+       char pad2[116];
+} __attribute__ ((packed));
+
+/* Datastructures for 3592 encryption support */
+
+struct tape3592_kekl {
+       __u8 flags;
+       char label[64];
+} __attribute__ ((packed));
+
+struct tape3592_kekl_pair {
+       __u8 count;
+       struct tape3592_kekl kekl[2];
+} __attribute__ ((packed));
+
+struct tape3592_kekl_query_data {
+       __u16 len;
+       __u8  fmt;
+       __u8  mc;
+       __u32 id;
+       __u8  flags;
+       struct tape3592_kekl_pair kekls;
+       char reserved[116];
+} __attribute__ ((packed));
+
+struct tape3592_kekl_query_order {
+       __u8 code;
+       __u8 flags;
+       char reserved1[2];
+       __u8 max_count;
+       char reserved2[35];
+} __attribute__ ((packed));
+
+struct tape3592_kekl_set_order {
+       __u8 code;
+       __u8 flags;
+       char reserved1[2];
+       __u8 op;
+       struct tape3592_kekl_pair kekls;
+       char reserved2[120];
 } __attribute__ ((packed));
 
 #endif /* _TAPE_3590_H */
index c8a89b3b87d4a2f421591779728bbc915b4af10d..dd0ecaed592e3998b0083c08363c6390c5f4183f 100644 (file)
@@ -73,7 +73,7 @@ tapeblock_trigger_requeue(struct tape_device *device)
 /*
  * Post finished request.
  */
-static inline void
+static void
 tapeblock_end_request(struct request *req, int uptodate)
 {
        if (end_that_request_first(req, uptodate, req->hard_nr_sectors))
@@ -108,7 +108,7 @@ __tapeblock_end_request(struct tape_request *ccw_req, void *data)
 /*
  * Feed the tape device CCW queue with requests supplied in a list.
  */
-static inline int
+static int
 tapeblock_start_request(struct tape_device *device, struct request *req)
 {
        struct tape_request *   ccw_req;
index 31198c8f27182701af403025a0078b5cbf554eaa..9faea04e11e9db2090ac7d7a0d9172c7e092d8f2 100644 (file)
@@ -3,7 +3,7 @@
  *    character device frontend for tape device driver
  *
  *  S390 and zSeries version
- *    Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *              Michael Holzheu <holzheu@de.ibm.com>
  *              Tuan Ngo-Anh <ngoanh@de.ibm.com>
@@ -89,22 +89,7 @@ tapechar_cleanup_device(struct tape_device *device)
        device->nt = NULL;
 }
 
-/*
- * Terminate write command (we write two TMs and skip backward over last)
- * This ensures that the tape is always correctly terminated.
- * When the user writes afterwards a new file, he will overwrite the
- * second TM and therefore one TM will remain to separate the
- * two files on the tape...
- */
-static inline void
-tapechar_terminate_write(struct tape_device *device)
-{
-       if (tape_mtop(device, MTWEOF, 1) == 0 &&
-           tape_mtop(device, MTWEOF, 1) == 0)
-               tape_mtop(device, MTBSR, 1);
-}
-
-static inline int
+static int
 tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
 {
        struct idal_buffer *new;
@@ -137,7 +122,7 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size)
 /*
  * Tape device read function
  */
-ssize_t
+static ssize_t
 tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
 {
        struct tape_device *device;
@@ -201,7 +186,7 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos)
 /*
  * Tape device write function
  */
-ssize_t
+static ssize_t
 tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos)
 {
        struct tape_device *device;
@@ -291,7 +276,7 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t
 /*
  * Character frontend tape device open function.
  */
-int
+static int
 tapechar_open (struct inode *inode, struct file *filp)
 {
        struct tape_device *device;
@@ -326,7 +311,7 @@ tapechar_open (struct inode *inode, struct file *filp)
  * Character frontend tape device release function.
  */
 
-int
+static int
 tapechar_release(struct inode *inode, struct file *filp)
 {
        struct tape_device *device;
index c6c2e918b990d3645bb5e384f9de4b4aae5804c4..e2a8a1a04bab46750240326cfce6ca4f634eca2c 100644 (file)
@@ -3,7 +3,7 @@
  *    basic function of the tape device driver
  *
  *  S390 and zSeries version
- *    Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2001,2006
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *              Michael Holzheu <holzheu@de.ibm.com>
  *              Tuan Ngo-Anh <ngoanh@de.ibm.com>
 #include "tape_std.h"
 
 #define PRINTK_HEADER "TAPE_CORE: "
+#define LONG_BUSY_TIMEOUT 180 /* seconds */
 
 static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *);
 static void tape_delayed_next_request(struct work_struct *);
+static void tape_long_busy_timeout(unsigned long data);
 
 /*
  * One list to contain all tape devices of all disciplines, so
@@ -69,10 +71,12 @@ const char *tape_op_verbose[TO_SIZE] =
        [TO_LOAD] = "LOA",      [TO_READ_CONFIG] = "RCF",
        [TO_READ_ATTMSG] = "RAT",
        [TO_DIS] = "DIS",       [TO_ASSIGN] = "ASS",
-       [TO_UNASSIGN] = "UAS"
+       [TO_UNASSIGN] = "UAS",  [TO_CRYPT_ON] = "CON",
+       [TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS",
+       [TO_KEKL_QUERY] = "KLQ",
 };
 
-static inline int
+static int
 busid_to_int(char *bus_id)
 {
        int     dec;
@@ -252,7 +256,7 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate)
 /*
  * Stop running ccw. Has to be called with the device lock held.
  */
-static inline int
+static int
 __tape_cancel_io(struct tape_device *device, struct tape_request *request)
 {
        int retries;
@@ -346,6 +350,9 @@ tape_generic_online(struct tape_device *device,
                return -EINVAL;
        }
 
+       init_timer(&device->lb_timeout);
+       device->lb_timeout.function = tape_long_busy_timeout;
+
        /* Let the discipline have a go at the device. */
        device->discipline = discipline;
        if (!try_module_get(discipline->owner)) {
@@ -385,7 +392,7 @@ out:
        return rc;
 }
 
-static inline void
+static void
 tape_cleanup_device(struct tape_device *device)
 {
        tapeblock_cleanup_device(device);
@@ -563,7 +570,7 @@ tape_generic_probe(struct ccw_device *cdev)
        return ret;
 }
 
-static inline void
+static void
 __tape_discard_requests(struct tape_device *device)
 {
        struct tape_request *   request;
@@ -703,7 +710,7 @@ tape_free_request (struct tape_request * request)
        kfree(request);
 }
 
-static inline int
+static int
 __tape_start_io(struct tape_device *device, struct tape_request *request)
 {
        int rc;
@@ -733,7 +740,7 @@ __tape_start_io(struct tape_device *device, struct tape_request *request)
        return rc;
 }
 
-static inline void
+static void
 __tape_start_next_request(struct tape_device *device)
 {
        struct list_head *l, *n;
@@ -801,7 +808,23 @@ tape_delayed_next_request(struct work_struct *work)
        spin_unlock_irq(get_ccwdev_lock(device->cdev));
 }
 
-static inline void
+static void tape_long_busy_timeout(unsigned long data)
+{
+       struct tape_request *request;
+       struct tape_device *device;
+
+       device = (struct tape_device *) data;
+       spin_lock_irq(get_ccwdev_lock(device->cdev));
+       request = list_entry(device->req_queue.next, struct tape_request, list);
+       if (request->status != TAPE_REQUEST_LONG_BUSY)
+               BUG();
+       DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id);
+       __tape_start_next_request(device);
+       device->lb_timeout.data = (unsigned long) tape_put_device(device);
+       spin_unlock_irq(get_ccwdev_lock(device->cdev));
+}
+
+static void
 __tape_end_request(
        struct tape_device *    device,
        struct tape_request *   request,
@@ -878,7 +901,7 @@ tape_dump_sense_dbf(struct tape_device *device, struct tape_request *request,
  * and starts it if the tape is idle. Has to be called with
  * the device lock held.
  */
-static inline int
+static int
 __tape_start_request(struct tape_device *device, struct tape_request *request)
 {
        int rc;
@@ -1094,7 +1117,22 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
        /* May be an unsolicited irq */
        if(request != NULL)
                request->rescnt = irb->scsw.count;
-
+       else if ((irb->scsw.dstat == 0x85 || irb->scsw.dstat == 0x80) &&
+                !list_empty(&device->req_queue)) {
+               /* Not Ready to Ready after long busy ? */
+               struct tape_request *req;
+               req = list_entry(device->req_queue.next,
+                                struct tape_request, list);
+               if (req->status == TAPE_REQUEST_LONG_BUSY) {
+                       DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id);
+                       if (del_timer(&device->lb_timeout)) {
+                               device->lb_timeout.data = (unsigned long)
+                                       tape_put_device(device);
+                               __tape_start_next_request(device);
+                       }
+                       return;
+               }
+       }
        if (irb->scsw.dstat != 0x0c) {
                /* Set the 'ONLINE' flag depending on sense byte 1 */
                if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE)
@@ -1142,6 +1180,15 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
                        break;
                case TAPE_IO_PENDING:
                        break;
+               case TAPE_IO_LONG_BUSY:
+                       device->lb_timeout.data =
+                               (unsigned long)tape_get_device_reference(device);
+                       device->lb_timeout.expires = jiffies +
+                               LONG_BUSY_TIMEOUT * HZ;
+                       DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id);
+                       add_timer(&device->lb_timeout);
+                       request->status = TAPE_REQUEST_LONG_BUSY;
+                       break;
                case TAPE_IO_RETRY:
                        rc = __tape_start_io(device, request);
                        if (rc)
index 09844621edc0f5e9d2476fd019e57ffb2af42506..bc33068b9ce2b3556bdc02ee0878ded5fb5233cc 100644 (file)
@@ -36,7 +36,7 @@
 struct tty_driver *tty3270_driver;
 static int tty3270_max_index;
 
-struct raw3270_fn tty3270_fn;
+static struct raw3270_fn tty3270_fn;
 
 struct tty3270_cell {
        unsigned char character;
@@ -119,8 +119,7 @@ static void tty3270_update(struct tty3270 *);
 /*
  * Setup timeout for a device. On timeout trigger an update.
  */
-void
-tty3270_set_timer(struct tty3270 *tp, int expires)
+static void tty3270_set_timer(struct tty3270 *tp, int expires)
 {
        if (expires == 0) {
                if (timer_pending(&tp->timer) && del_timer(&tp->timer))
@@ -841,7 +840,7 @@ tty3270_del_views(void)
        }
 }
 
-struct raw3270_fn tty3270_fn = {
+static struct raw3270_fn tty3270_fn = {
        .activate = tty3270_activate,
        .deactivate = tty3270_deactivate,
        .intv = (void *) tty3270_irq,
@@ -1754,8 +1753,7 @@ static const struct tty_operations tty3270_ops = {
        .set_termios = tty3270_set_termios
 };
 
-void
-tty3270_notifier(int index, int active)
+static void tty3270_notifier(int index, int active)
 {
        if (active)
                tty_register_device(tty3270_driver, index, NULL);
@@ -1767,8 +1765,7 @@ tty3270_notifier(int index, int active)
  * 3270 tty registration code called from tty_init().
  * Most kernel services (incl. kmalloc) are available at this poimt.
  */
-int __init
-tty3270_init(void)
+static int __init tty3270_init(void)
 {
        struct tty_driver *driver;
        int ret;
index 6cb23040954b4778de47f299a0ffc8c6d50cb9ce..4f894dc2373bbc68230f5c2cb9fe31c1f1b913a2 100644 (file)
@@ -128,9 +128,8 @@ static iucv_interrupt_ops_t vmlogrdr_iucvops = {
        .MessagePending     = vmlogrdr_iucv_MessagePending,
 };
 
-
-DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
-DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
+static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue);
+static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue);
 
 /*
  * pointer to system service private structure
index 12c2d6b746e697b5e017d6414f2281a509aae1ff..aa65df4dfcedf174aaa337d2fe42105c5c9cc731 100644 (file)
@@ -43,7 +43,7 @@ typedef enum {add, free} range_action;
  * Function: blacklist_range
  * (Un-)blacklist the devices from-to
  */
-static inline void
+static void
 blacklist_range (range_action action, unsigned int from, unsigned int to,
                 unsigned int ssid)
 {
@@ -69,7 +69,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to,
  * Get devno/busid from given string.
  * Shamelessly grabbed from dasd_devmap.c.
  */
-static inline int
+static int
 blacklist_busid(char **str, int *id0, int *ssid, int *devno)
 {
        int val, old_style;
@@ -123,10 +123,10 @@ confused:
        return 1;
 }
 
-static inline int
+static int
 blacklist_parse_parameters (char *str, range_action action)
 {
-       unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid;
+       int from, to, from_id0, to_id0, from_ssid, to_ssid;
 
        while (*str != 0 && *str != '\n') {
                range_action ra = action;
@@ -227,7 +227,7 @@ is_blacklisted (int ssid, int devno)
  * Function: blacklist_parse_proc_parameters
  * parse the stuff which is piped to /proc/cio_ignore
  */
-static inline void
+static void
 blacklist_parse_proc_parameters (char *buf)
 {
        if (strncmp (buf, "free ", 5) == 0) {
index 38954f5cd14c8d542c92999ddcdf3fc7f6d337ef..d48e3ca4752c444ba5d58d3c38abaa6a2daeeed9 100644 (file)
@@ -53,7 +53,7 @@ ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
 
 static struct bus_type ccwgroup_bus_type;
 
-static inline void
+static void
 __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
 {
        int i;
@@ -104,7 +104,7 @@ ccwgroup_release (struct device *dev)
        kfree(gdev);
 }
 
-static inline int
+static int
 __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
 {
        char str[8];
@@ -424,7 +424,7 @@ ccwgroup_probe_ccwdev(struct ccw_device *cdev)
        return 0;
 }
 
-static inline struct ccwgroup_device *
+static struct ccwgroup_device *
 __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
 {
        struct ccwgroup_device *gdev;
index cbab8d2ce5cfd664b82fd6f189a0fbc9dfbbfb38..6f05a44e38170c9df7d662298256a986d3873fd0 100644 (file)
@@ -93,7 +93,7 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page)
                u16 sch;          /* subchannel */
                u8 chpid[8];      /* chpids 0-7 */
                u16 fla[8];       /* full link addresses 0-7 */
-       } *ssd_area;
+       } __attribute__ ((packed)) *ssd_area;
 
        ssd_area = page;
 
@@ -277,7 +277,7 @@ out_unreg:
        return 0;
 }
 
-static inline void
+static void
 s390_set_chpid_offline( __u8 chpid)
 {
        char dbf_txt[15];
@@ -338,7 +338,7 @@ s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch)
        return 0x80 >> chp;
 }
 
-static inline int
+static int
 s390_process_res_acc_new_sch(struct subchannel_id schid)
 {
        struct schib schib;
@@ -444,7 +444,7 @@ __get_chpid_from_lir(void *data)
                u32 andesc[28];
                /* incident-specific information */
                u32 isinfo[28];
-       } *lir;
+       } __attribute__ ((packed)) *lir;
 
        lir = data;
        if (!(lir->iq&0x80))
@@ -461,154 +461,146 @@ __get_chpid_from_lir(void *data)
        return (u16) (lir->indesc[0]&0x000000ff);
 }
 
-int
-chsc_process_crw(void)
+struct chsc_sei_area {
+       struct chsc_header request;
+       u32 reserved1;
+       u32 reserved2;
+       u32 reserved3;
+       struct chsc_header response;
+       u32 reserved4;
+       u8  flags;
+       u8  vf;         /* validity flags */
+       u8  rs;         /* reporting source */
+       u8  cc;         /* content code */
+       u16 fla;        /* full link address */
+       u16 rsid;       /* reporting source id */
+       u32 reserved5;
+       u32 reserved6;
+       u8 ccdf[4096 - 16 - 24];        /* content-code dependent field */
+       /* ccdf has to be big enough for a link-incident record */
+} __attribute__ ((packed));
+
+static int chsc_process_sei_link_incident(struct chsc_sei_area *sei_area)
+{
+       int chpid;
+
+       CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n",
+                     sei_area->rs, sei_area->rsid);
+       if (sei_area->rs != 4)
+               return 0;
+       chpid = __get_chpid_from_lir(sei_area->ccdf);
+       if (chpid < 0)
+               CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n");
+       else
+               s390_set_chpid_offline(chpid);
+
+       return 0;
+}
+
+static int chsc_process_sei_res_acc(struct chsc_sei_area *sei_area)
 {
-       int chpid, ret;
        struct res_acc_data res_data;
-       struct {
-               struct chsc_header request;
-               u32 reserved1;
-               u32 reserved2;
-               u32 reserved3;
-               struct chsc_header response;
-               u32 reserved4;
-               u8  flags;
-               u8  vf;         /* validity flags */
-               u8  rs;         /* reporting source */
-               u8  cc;         /* content code */
-               u16 fla;        /* full link address */
-               u16 rsid;       /* reporting source id */
-               u32 reserved5;
-               u32 reserved6;
-               u32 ccdf[96];   /* content-code dependent field */
-               /* ccdf has to be big enough for a link-incident record */
-       } *sei_area;
+       struct device *dev;
+       int status;
+       int rc;
+
+       CIO_CRW_EVENT(4, "chsc: resource accessibility event (rs=%02x, "
+                     "rs_id=%04x)\n", sei_area->rs, sei_area->rsid);
+       if (sei_area->rs != 4)
+               return 0;
+       /* allocate a new channel path structure, if needed */
+       status = get_chp_status(sei_area->rsid);
+       if (status < 0)
+               new_channel_path(sei_area->rsid);
+       else if (!status)
+               return 0;
+       dev = get_device(&css[0]->chps[sei_area->rsid]->dev);
+       memset(&res_data, 0, sizeof(struct res_acc_data));
+       res_data.chp = to_channelpath(dev);
+       if ((sei_area->vf & 0xc0) != 0) {
+               res_data.fla = sei_area->fla;
+               if ((sei_area->vf & 0xc0) == 0xc0)
+                       /* full link address */
+                       res_data.fla_mask = 0xffff;
+               else
+                       /* link address */
+                       res_data.fla_mask = 0xff00;
+       }
+       rc = s390_process_res_acc(&res_data);
+       put_device(dev);
+
+       return rc;
+}
+
+static int chsc_process_sei(struct chsc_sei_area *sei_area)
+{
+       int rc;
+
+       /* Check if we might have lost some information. */
+       if (sei_area->flags & 0x40)
+               CIO_CRW_EVENT(2, "chsc: event overflow\n");
+       /* which kind of information was stored? */
+       rc = 0;
+       switch (sei_area->cc) {
+       case 1: /* link incident*/
+               rc = chsc_process_sei_link_incident(sei_area);
+               break;
+       case 2: /* i/o resource accessibiliy */
+               rc = chsc_process_sei_res_acc(sei_area);
+               break;
+       default: /* other stuff */
+               CIO_CRW_EVENT(4, "chsc: unhandled sei content code %d\n",
+                             sei_area->cc);
+               break;
+       }
+
+       return rc;
+}
+
+int chsc_process_crw(void)
+{
+       struct chsc_sei_area *sei_area;
+       int ret;
+       int rc;
 
        if (!sei_page)
                return 0;
-       /*
-        * build the chsc request block for store event information
-        * and do the call
-        * This function is only called by the machine check handler thread,
-        * so we don't need locking for the sei_page.
-        */
+       /* Access to sei_page is serialized through machine check handler
+        * thread, so no need for locking. */
        sei_area = sei_page;
 
        CIO_TRACE_EVENT( 2, "prcss");
        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.length = 0x0010;
                sei_area->request.code = 0x000e;
+               if (chsc(sei_area))
+                       break;
 
-               ccode = chsc(sei_area);
-               if (ccode > 0)
-                       return 0;
-
-               switch (sei_area->response.code) {
-                       /* for debug purposes, check for problems */
-               case 0x0001:
-                       CIO_CRW_EVENT(4, "chsc_process_crw: event information "
-                                       "successfully stored\n");
-                       break; /* everything ok */
-               case 0x0002:
-                       CIO_CRW_EVENT(2,
-                                     "chsc_process_crw: invalid command!\n");
-                       return 0;
-               case 0x0003:
-                       CIO_CRW_EVENT(2, "chsc_process_crw: error in chsc "
-                                     "request block!\n");
-                       return 0;
-               case 0x0005:
-                       CIO_CRW_EVENT(2, "chsc_process_crw: no event "
-                                     "information stored\n");
-                       return 0;
-               default:
-                       CIO_CRW_EVENT(2, "chsc_process_crw: chsc response %d\n",
+               if (sei_area->response.code == 0x0001) {
+                       CIO_CRW_EVENT(4, "chsc: sei successful\n");
+                       rc = chsc_process_sei(sei_area);
+                       if (rc)
+                               ret = rc;
+               } else {
+                       CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
                                      sei_area->response.code);
-                       return 0;
-               }
-
-               /* Check if we might have lost some information. */
-               if (sei_area->flags & 0x40)
-                       CIO_CRW_EVENT(2, "chsc_process_crw: Event information "
-                                      "has been lost due to overflow!\n");
-
-               if (sei_area->rs != 4) {
-                       CIO_CRW_EVENT(2, "chsc_process_crw: reporting source "
-                                     "(%04X) isn't a chpid!\n",
-                                     sei_area->rsid);
-                       continue;
-               }
-
-               /* which kind of information was stored? */
-               switch (sei_area->cc) {
-               case 1: /* link incident*/
-                       CIO_CRW_EVENT(4, "chsc_process_crw: "
-                                     "channel subsystem reports link incident,"
-                                     " reporting source is chpid %x\n",
-                                     sei_area->rsid);
-                       chpid = __get_chpid_from_lir(sei_area->ccdf);
-                       if (chpid < 0)
-                               CIO_CRW_EVENT(4, "%s: Invalid LIR, skipping\n",
-                                             __FUNCTION__);
-                       else
-                               s390_set_chpid_offline(chpid);
-                       break;
-                       
-               case 2: /* i/o resource accessibiliy */
-                       CIO_CRW_EVENT(4, "chsc_process_crw: "
-                                     "channel subsystem reports some I/O "
-                                     "devices may have become accessible\n");
-                       pr_debug("Data received after sei: \n");
-                       pr_debug("Validity flags: %x\n", sei_area->vf);
-                       
-                       /* allocate a new channel path structure, if needed */
-                       status = get_chp_status(sei_area->rsid);
-                       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;
-                               }
-                       }
-                       ret = s390_process_res_acc(&res_data);
-                       pr_debug("\n\n");
-                       put_device(dev);
-                       break;
-                       
-               default: /* other stuff */
-                       CIO_CRW_EVENT(4, "chsc_process_crw: event %d\n",
-                                     sei_area->cc);
+                       ret = 0;
                        break;
                }
        } while (sei_area->flags & 0x80);
+
        return ret;
 }
 
-static inline int
+static int
 __chp_add_new_sch(struct subchannel_id schid)
 {
        struct schib schib;
        int ret;
 
-       if (stsch(schid, &schib))
+       if (stsch_err(schid, &schib))
                /* We're through */
                return need_rescan ? -EAGAIN : -ENXIO;
 
@@ -709,7 +701,7 @@ chp_process_crw(int chpid, int on)
        return chp_add(chpid);
 }
 
-static inline int check_for_io_on_path(struct subchannel *sch, int index)
+static int check_for_io_on_path(struct subchannel *sch, int index)
 {
        int cc;
 
@@ -741,7 +733,7 @@ static void terminate_internal_io(struct subchannel *sch)
                sch->driver->termination(&sch->dev);
 }
 
-static inline void
+static void
 __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
 {
        int chp, old_lpm;
@@ -967,8 +959,8 @@ static struct bin_attribute chp_measurement_attr = {
 static void
 chsc_remove_chp_cmg_attr(struct channel_path *chp)
 {
-       sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_chars_attr);
-       sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_attr);
+       device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr);
+       device_remove_bin_file(&chp->dev, &chp_measurement_attr);
 }
 
 static int
@@ -976,14 +968,12 @@ chsc_add_chp_cmg_attr(struct channel_path *chp)
 {
        int ret;
 
-       ret = sysfs_create_bin_file(&chp->dev.kobj,
-                                   &chp_measurement_chars_attr);
+       ret = device_create_bin_file(&chp->dev, &chp_measurement_chars_attr);
        if (ret)
                return ret;
-       ret = sysfs_create_bin_file(&chp->dev.kobj, &chp_measurement_attr);
+       ret = device_create_bin_file(&chp->dev, &chp_measurement_attr);
        if (ret)
-               sysfs_remove_bin_file(&chp->dev.kobj,
-                                     &chp_measurement_chars_attr);
+               device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr);
        return ret;
 }
 
@@ -1042,7 +1032,7 @@ __chsc_do_secm(struct channel_subsystem *css, int enable, void *page)
                u32 : 4;
                u32 fmt : 4;
                u32 : 16;
-       } *secm_area;
+       } __attribute__ ((packed)) *secm_area;
        int ret, ccode;
 
        secm_area = page;
@@ -1253,7 +1243,7 @@ chsc_determine_channel_path_description(int chpid,
                struct chsc_header response;
                u32 zeroes2;
                struct channel_path_desc desc;
-       } *scpd_area;
+       } __attribute__ ((packed)) *scpd_area;
 
        scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
        if (!scpd_area)
@@ -1350,7 +1340,7 @@ chsc_get_channel_measurement_chars(struct channel_path *chp)
                u32 cmg : 8;
                u32 zeroes3;
                u32 data[NR_MEASUREMENT_CHARS];
-       } *scmc_area;
+       } __attribute__ ((packed)) *scmc_area;
 
        scmc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
        if (!scmc_area)
@@ -1517,7 +1507,7 @@ chsc_enable_facility(int operation_code)
                u32 reserved5:4;
                u32 format2:4;
                u32 reserved6:24;
-       } *sda_area;
+       } __attribute__ ((packed)) *sda_area;
 
        sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA);
        if (!sda_area)
@@ -1569,7 +1559,7 @@ chsc_determine_css_characteristics(void)
                u32 reserved4;
                u32 general_char[510];
                u32 chsc_char[518];
-       } *scsc_area;
+       } __attribute__ ((packed)) *scsc_area;
 
        scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
        if (!scsc_area) {
index a259245780ae7465d1be49fe442c076d32324585..0fb2b024208f2ce07faea9661fb1eefe4f0cf737 100644 (file)
 struct chsc_header {
        u16 length;
        u16 code;
-};
+} __attribute__ ((packed));
 
 #define NR_MEASUREMENT_CHARS 5
 struct cmg_chars {
        u32 values[NR_MEASUREMENT_CHARS];
-};
+} __attribute__ ((packed));
 
 #define NR_MEASUREMENT_ENTRIES 8
 struct cmg_entry {
        u32 values[NR_MEASUREMENT_ENTRIES];
-};
+} __attribute__ ((packed));
 
 struct channel_path_desc {
        u8 flags;
@@ -31,7 +31,7 @@ struct channel_path_desc {
        u8 zeroes;
        u8 chla;
        u8 chpp;
-};
+} __attribute__ ((packed));
 
 struct channel_path {
        int id;
@@ -47,6 +47,9 @@ struct channel_path {
 extern void s390_process_css( void );
 extern void chsc_validate_chpids(struct subchannel *);
 extern void chpid_is_actually_online(int);
+extern int css_get_ssd_info(struct subchannel *);
+extern int chsc_process_crw(void);
+extern int chp_process_crw(int, int);
 
 struct css_general_char {
        u64 : 41;
index ae1bf231d08945bcad13903266f44ad1a3a00be6..b3a56dc5f68a2fd5144dad6d7bd6abef50369fd0 100644 (file)
@@ -122,7 +122,7 @@ cio_get_options (struct subchannel *sch)
  * Use tpi to get a pending interrupt, call the interrupt handler and
  * return a pointer to the subchannel structure.
  */
-static inline int
+static int
 cio_tpi(void)
 {
        struct tpi_info *tpi_info;
@@ -152,7 +152,7 @@ cio_tpi(void)
        return 1;
 }
 
-static inline int
+static int
 cio_start_handle_notoper(struct subchannel *sch, __u8 lpm)
 {
        char dbf_text[15];
@@ -585,7 +585,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid)
                 * 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 "
+               CIO_MSG_EVENT(4, "Blacklisted device detected "
                              "at devno %04X, subchannel set %x\n",
                              sch->schib.pmcw.dev, sch->schid.ssid);
                err = -ENODEV;
@@ -646,7 +646,7 @@ do_IRQ (struct pt_regs *regs)
                 * Make sure that the i/o interrupt did not "overtake"
                 * the last HZ timer interrupt.
                 */
-               account_ticks();
+               account_ticks(S390_lowcore.int_clock);
        /*
         * Get interrupt information from lowcore
         */
@@ -832,7 +832,7 @@ cio_get_console_subchannel(void)
 }
 
 #endif
-static inline int
+static int
 __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
 {
        int retry, cc;
@@ -850,7 +850,20 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
        return -EBUSY; /* uhm... */
 }
 
-static inline int
+/* we can't use the normal udelay here, since it enables external interrupts */
+
+static void udelay_reset(unsigned long usecs)
+{
+       uint64_t start_cc, end_cc;
+
+       asm volatile ("STCK %0" : "=m" (start_cc));
+       do {
+               cpu_relax();
+               asm volatile ("STCK %0" : "=m" (end_cc));
+       } while (((end_cc - start_cc)/4096) < usecs);
+}
+
+static int
 __clear_subchannel_easy(struct subchannel_id schid)
 {
        int retry;
@@ -865,7 +878,7 @@ __clear_subchannel_easy(struct subchannel_id schid)
                        if (schid_equal(&ti.schid, &schid))
                                return 0;
                }
-               udelay(100);
+               udelay_reset(100);
        }
        return -EBUSY;
 }
@@ -882,11 +895,11 @@ static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
        int rc;
 
        pgm_check_occured = 0;
-       s390_reset_pgm_handler = cio_reset_pgm_check_handler;
+       s390_base_pgm_handler_fn = cio_reset_pgm_check_handler;
        rc = stsch(schid, addr);
-       s390_reset_pgm_handler = NULL;
+       s390_base_pgm_handler_fn = NULL;
 
-       /* The program check handler could have changed pgm_check_occured */
+       /* The program check handler could have changed pgm_check_occured. */
        barrier();
 
        if (pgm_check_occured)
@@ -944,7 +957,7 @@ static void css_reset(void)
        /* Reset subchannels. */
        for_each_subchannel(__shutdown_subchannel_easy,  NULL);
        /* Reset channel paths. */
-       s390_reset_mcck_handler = s390_reset_chpids_mcck_handler;
+       s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler;
        /* Enable channel report machine checks. */
        __ctl_set_bit(14, 28);
        /* Temporarily reenable machine checks. */
@@ -969,7 +982,7 @@ static void css_reset(void)
        local_mcck_disable();
        /* Disable channel report machine checks. */
        __ctl_clear_bit(14, 28);
-       s390_reset_mcck_handler = NULL;
+       s390_base_mcck_handler_fn = NULL;
 }
 
 static struct reset_call css_reset_call = {
index 828b2d334f0a30fde8a687b7ac5587927151aa6f..90b22faabbf711ea621a9b7a833552053be23517 100644 (file)
@@ -519,8 +519,8 @@ struct cmb {
 /* insert a single device into the cmb_area list
  * called with cmb_area.lock held from alloc_cmb
  */
-static inline int alloc_cmb_single (struct ccw_device *cdev,
-                                   struct cmb_data *cmb_data)
+static int alloc_cmb_single(struct ccw_device *cdev,
+                           struct cmb_data *cmb_data)
 {
        struct cmb *cmb;
        struct ccw_device_private *node;
index 9d6c02446863cffa2eb1063962781248cae5f574..fe0ace7aece8e65edeaac816637ab135af8ef6f7 100644 (file)
@@ -30,7 +30,7 @@ struct channel_subsystem *css[__MAX_CSSID + 1];
 
 int css_characteristics_avail = 0;
 
-inline int
+int
 for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
 {
        struct subchannel_id schid;
@@ -108,9 +108,6 @@ css_subchannel_release(struct device *dev)
        }
 }
 
-extern int css_get_ssd_info(struct subchannel *sch);
-
-
 int css_sch_device_register(struct subchannel *sch)
 {
        int ret;
@@ -187,7 +184,7 @@ get_subchannel_by_schid(struct subchannel_id schid)
        return dev ? to_subchannel(dev) : NULL;
 }
 
-static inline int css_get_subchannel_status(struct subchannel *sch)
+static int css_get_subchannel_status(struct subchannel *sch)
 {
        struct schib schib;
 
@@ -299,7 +296,7 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
                /* Will be done on the slow path. */
                return -EAGAIN;
        }
-       if (stsch(schid, &schib) || !schib.pmcw.dnv) {
+       if (stsch_err(schid, &schib) || !schib.pmcw.dnv) {
                /* Unusable - ignore. */
                return 0;
        }
@@ -417,7 +414,7 @@ static void reprobe_all(struct work_struct *unused)
                      need_reprobe);
 }
 
-DECLARE_WORK(css_reprobe_work, reprobe_all);
+static DECLARE_WORK(css_reprobe_work, reprobe_all);
 
 /* Schedule reprobing of all unregistered subchannels. */
 void css_schedule_reprobe(void)
@@ -578,7 +575,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr,
 
 static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store);
 
-static inline int __init setup_css(int nr)
+static int __init setup_css(int nr)
 {
        u32 tod_high;
        int ret;
index 3464c5b875c470d8436f8054c740ff6a17f661f0..ca2bab932a8a76257579496f1024407fe44befb2 100644 (file)
@@ -143,6 +143,8 @@ extern void css_sch_device_unregister(struct subchannel *);
 extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
 extern int css_init_done;
 extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
+extern int css_process_crw(int, int);
+extern void css_reiterate_subchannels(void);
 
 #define __MAX_SUBCHANNEL 65535
 #define __MAX_SSID 3
index 803579053c2fe012dbf4854b13c12baa156a8f86..e322111fb3696bb066f0b6758a2491d977422c14 100644 (file)
@@ -138,7 +138,6 @@ struct bus_type ccw_bus_type;
 
 static int io_subchannel_probe (struct subchannel *);
 static int io_subchannel_remove (struct subchannel *);
-void io_subchannel_irq (struct device *);
 static int io_subchannel_notify(struct device *, int);
 static void io_subchannel_verify(struct device *);
 static void io_subchannel_ioterm(struct device *);
@@ -235,11 +234,8 @@ chpids_show (struct device * dev, struct device_attribute *attr, char * buf)
        ssize_t ret = 0;
        int chp;
 
-       if (ssd)
-               for (chp = 0; chp < 8; chp++)
-                       ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]);
-       else
-               ret += sprintf (buf, "n/a");
+       for (chp = 0; chp < 8; chp++)
+               ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]);
        ret += sprintf (buf+ret, "\n");
        return min((ssize_t)PAGE_SIZE, ret);
 }
@@ -552,13 +548,13 @@ static struct attribute_group ccwdev_attr_group = {
        .attrs = ccwdev_attrs,
 };
 
-static inline int
+static int
 device_add_files (struct device *dev)
 {
        return sysfs_create_group(&dev->kobj, &ccwdev_attr_group);
 }
 
-static inline void
+static void
 device_remove_files(struct device *dev)
 {
        sysfs_remove_group(&dev->kobj, &ccwdev_attr_group);
index 29db6341d632ce0bd5a9f78b6982c3367a388349..b66338b7657936d7de03780537637f81f559ad4f 100644 (file)
@@ -74,6 +74,7 @@ extern struct workqueue_struct *ccw_device_notify_work;
 extern wait_queue_head_t ccw_device_init_wq;
 extern atomic_t ccw_device_init_count;
 
+void io_subchannel_irq (struct device *pdev);
 void io_subchannel_recog_done(struct ccw_device *cdev);
 
 int ccw_device_cancel_halt_clear(struct ccw_device *);
@@ -118,6 +119,7 @@ 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 *);
+extern struct bus_type ccw_bus_type;
 
 /* Channel measurement facility related */
 void retry_set_schib(struct ccw_device *cdev);
index eed14572fc3b01e3445ee30a46e30bae6a15a006..51238e7555bb9d34bcbc23272f265e2769e481d7 100644 (file)
@@ -206,7 +206,7 @@ ccw_device_handle_oper(struct ccw_device *cdev)
  * been varied online on the SE so we have to find out by magic (i. e. driving
  * the channel subsystem to device selection and updating our path masks).
  */
-static inline void
+static void
 __recover_lost_chpids(struct subchannel *sch, int old_lpm)
 {
        int mask, i;
@@ -387,7 +387,7 @@ ccw_device_done(struct ccw_device *cdev, int state)
                put_device (&cdev->dev);
 }
 
-static inline int cmp_pgid(struct pgid *p1, struct pgid *p2)
+static int cmp_pgid(struct pgid *p1, struct pgid *p2)
 {
        char *c1;
        char *c2;
@@ -842,6 +842,8 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event)
 call_handler_unsol:
                if (cdev->handler)
                        cdev->handler (cdev, 0, irb);
+               if (cdev->private->flags.doverify)
+                       ccw_device_online_verify(cdev, 0);
                return;
        }
        /* Accumulate status and find out if a basic sense is needed. */
@@ -892,7 +894,7 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
 /*
  * Got an interrupt for a basic sense.
  */
-void
+static void
 ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
 {
        struct irb *irb;
index d269607336ec212368d7302511426c43c7cefab0..d7b25b8f71d236e9c783fcafedfaa853a074344d 100644 (file)
@@ -302,7 +302,7 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb)
        wake_up(&cdev->private->wait_q);
 }
 
-static inline int
+static int
 __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, __u8 lpm)
 {
        int ret;
index bdcf930f7beb120a636565f461ac32c9e9c6b9c0..6b1caea622ea8a1b3ee416477d8de1514ab99fa7 100644 (file)
@@ -25,7 +25,7 @@
  * Check for any kind of channel or interface control check but don't
  * issue the message for the console device
  */
-static inline void
+static void
 ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb)
 {
        if (!(irb->scsw.cstat & (SCHN_STAT_CHN_DATA_CHK |
@@ -72,7 +72,7 @@ ccw_device_path_notoper(struct ccw_device *cdev)
 /*
  * Copy valid bits from the extended control word to device irb.
  */
-static inline void
+static void
 ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb)
 {
        /*
@@ -94,7 +94,7 @@ ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb)
 /*
  * Check if extended status word is valid.
  */
-static inline int
+static int
 ccw_device_accumulate_esw_valid(struct irb *irb)
 {
        if (!irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND)
@@ -109,7 +109,7 @@ ccw_device_accumulate_esw_valid(struct irb *irb)
 /*
  * Copy valid bits from the extended status word to device irb.
  */
-static inline void
+static void
 ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb)
 {
        struct irb *cdev_irb;
index 6fd1940842ebd05d9185b6959fae90e37653546b..d726cd5777dedbf789cda3a2188cb0a522a8be90 100644 (file)
@@ -66,7 +66,6 @@ MODULE_LICENSE("GPL");
 /******************** HERE WE GO ***********************************/
 
 static const char version[] = "QDIO base support version 2";
-extern struct bus_type ccw_bus_type;
 
 static int qdio_performance_stats = 0;
 static int proc_perf_file_registration;
@@ -138,7 +137,7 @@ qdio_release_q(struct qdio_q *q)
 }
 
 /*check ccq  */
-static inline int
+static int
 qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
 {
        char dbf_text[15];
@@ -153,7 +152,7 @@ qdio_check_ccq(struct qdio_q *q, unsigned int ccq)
        return -EIO;
 }
 /* EQBS: extract buffer states */
-static inline int
+static int
 qdio_do_eqbs(struct qdio_q *q, unsigned char *state,
             unsigned int *start, unsigned int *cnt)
 {
@@ -188,7 +187,7 @@ again:
 }
 
 /* SQBS: set buffer states */
-static inline int
+static int
 qdio_do_sqbs(struct qdio_q *q, unsigned char state,
             unsigned int *start, unsigned int *cnt)
 {
@@ -315,7 +314,7 @@ __do_siga_output(struct qdio_q *q, unsigned int *busy_bit)
  * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns
  * an access exception 
  */
-static inline int 
+static int
 qdio_siga_output(struct qdio_q *q)
 {
        int cc;
@@ -349,7 +348,7 @@ qdio_siga_output(struct qdio_q *q)
        return cc;
 }
 
-static inline int 
+static int
 qdio_siga_input(struct qdio_q *q)
 {
        int cc;
@@ -421,7 +420,7 @@ tiqdio_sched_tl(void)
        tasklet_hi_schedule(&tiqdio_tasklet);
 }
 
-static inline void
+static void
 qdio_mark_tiq(struct qdio_q *q)
 {
        unsigned long flags;
@@ -471,7 +470,7 @@ qdio_mark_q(struct qdio_q *q)
        tasklet_schedule(&q->tasklet);
 }
 
-static inline int
+static int
 qdio_stop_polling(struct qdio_q *q)
 {
 #ifdef QDIO_USE_PROCESSING_STATE
@@ -525,7 +524,7 @@ qdio_stop_polling(struct qdio_q *q)
  * sophisticated locking outside of unmark_q, so that we don't need to
  * disable the interrupts :-) 
 */
-static inline void
+static void
 qdio_unmark_q(struct qdio_q *q)
 {
        unsigned long flags;
@@ -691,7 +690,7 @@ qdio_qebsm_get_inbound_buffer_frontier(struct qdio_q *q)
         return q->first_to_check;
 }
 
-static inline int
+static int
 qdio_get_outbound_buffer_frontier(struct qdio_q *q)
 {
        struct qdio_irq *irq;
@@ -774,7 +773,7 @@ out:
 }
 
 /* all buffers are processed */
-static inline int
+static int
 qdio_is_outbound_q_done(struct qdio_q *q)
 {
        int no_used;
@@ -796,7 +795,7 @@ qdio_is_outbound_q_done(struct qdio_q *q)
        return (no_used==0);
 }
 
-static inline int
+static int
 qdio_has_outbound_q_moved(struct qdio_q *q)
 {
        int i;
@@ -816,7 +815,7 @@ qdio_has_outbound_q_moved(struct qdio_q *q)
        }
 }
 
-static inline void
+static void
 qdio_kick_outbound_q(struct qdio_q *q)
 {
        int result;
@@ -905,7 +904,7 @@ qdio_kick_outbound_q(struct qdio_q *q)
        }
 }
 
-static inline void
+static void
 qdio_kick_outbound_handler(struct qdio_q *q)
 {
        int start, end, real_end, count;
@@ -942,7 +941,7 @@ qdio_kick_outbound_handler(struct qdio_q *q)
        q->error_status_flags=0;
 }
 
-static inline void
+static void
 __qdio_outbound_processing(struct qdio_q *q)
 {
        int siga_attempts;
@@ -1002,7 +1001,7 @@ qdio_outbound_processing(struct qdio_q *q)
 /************************* INBOUND ROUTINES *******************************/
 
 
-static inline int
+static int
 qdio_get_inbound_buffer_frontier(struct qdio_q *q)
 {
        struct qdio_irq *irq;
@@ -1133,7 +1132,7 @@ out:
        return q->first_to_check;
 }
 
-static inline int
+static int
 qdio_has_inbound_q_moved(struct qdio_q *q)
 {
        int i;
@@ -1167,7 +1166,7 @@ qdio_has_inbound_q_moved(struct qdio_q *q)
 }
 
 /* means, no more buffers to be filled */
-static inline int
+static int
 tiqdio_is_inbound_q_done(struct qdio_q *q)
 {
        int no_used;
@@ -1228,7 +1227,7 @@ tiqdio_is_inbound_q_done(struct qdio_q *q)
        return 0;
 }
 
-static inline int
+static int
 qdio_is_inbound_q_done(struct qdio_q *q)
 {
        int no_used;
@@ -1296,7 +1295,7 @@ qdio_is_inbound_q_done(struct qdio_q *q)
        }
 }
 
-static inline void
+static void
 qdio_kick_inbound_handler(struct qdio_q *q)
 {
        int count, start, end, real_end, i;
@@ -1343,7 +1342,7 @@ qdio_kick_inbound_handler(struct qdio_q *q)
        }
 }
 
-static inline void
+static void
 __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set)
 {
        struct qdio_irq *irq_ptr;
@@ -1442,7 +1441,7 @@ tiqdio_inbound_processing(struct qdio_q *q)
        __tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount));
 }
 
-static inline void
+static void
 __qdio_inbound_processing(struct qdio_q *q)
 {
        int q_laps=0;
@@ -1493,7 +1492,7 @@ qdio_inbound_processing(struct qdio_q *q)
 /************************* MAIN ROUTINES *******************************/
 
 #ifdef QDIO_USE_PROCESSING_STATE
-static inline int
+static int
 tiqdio_reset_processing_state(struct qdio_q *q, int q_laps)
 {
        if (!q) {
@@ -1545,7 +1544,7 @@ tiqdio_reset_processing_state(struct qdio_q *q, int q_laps)
 }
 #endif /* QDIO_USE_PROCESSING_STATE */
 
-static inline void
+static void
 tiqdio_inbound_checks(void)
 {
        struct qdio_q *q;
@@ -1949,7 +1948,7 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state)
        mb();
 }
 
-static inline void
+static void
 qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb)
 {
        char dbf_text[15];
@@ -1966,7 +1965,7 @@ qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb)
                
 }
 
-static inline void
+static void
 qdio_handle_pci(struct qdio_irq *irq_ptr)
 {
        int i;
@@ -2002,7 +2001,7 @@ qdio_handle_pci(struct qdio_irq *irq_ptr)
 
 static void qdio_establish_handle_irq(struct ccw_device*, int, int);
 
-static inline void
+static void
 qdio_handle_activate_check(struct ccw_device *cdev, unsigned long intparm,
                           int cstat, int dstat)
 {
@@ -2229,7 +2228,7 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags,
        return cc;
 }
 
-static inline void
+static void
 qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac,
                            unsigned long token)
 {
@@ -2740,7 +2739,7 @@ qdio_free(struct ccw_device *cdev)
        return 0;
 }
 
-static inline void
+static void
 qdio_allocate_do_dbf(struct qdio_initialize *init_data)
 {
        char dbf_text[20]; /* if a printf printed out more than 8 chars */
@@ -2773,7 +2772,7 @@ qdio_allocate_do_dbf(struct qdio_initialize *init_data)
        QDIO_DBF_HEX0(0,setup,&init_data->output_sbal_addr_array,sizeof(void*));
 }
 
-static inline void
+static void
 qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt)
 {
        irq_ptr->input_qs[i]->is_iqdio_q = iqfmt;
@@ -2792,7 +2791,7 @@ qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt)
        irq_ptr->qdr->qdf0[i].dkey=QDIO_STORAGE_KEY;
 }
 
-static inline void
+static void
 qdio_allocate_fill_output_desc(struct qdio_irq *irq_ptr, int i,
                               int j, int iqfmt)
 {
@@ -2813,7 +2812,7 @@ qdio_allocate_fill_output_desc(struct qdio_irq *irq_ptr, int i,
 }
 
 
-static inline void
+static void
 qdio_initialize_set_siga_flags_input(struct qdio_irq *irq_ptr)
 {
        int i;
@@ -2839,7 +2838,7 @@ qdio_initialize_set_siga_flags_input(struct qdio_irq *irq_ptr)
        }
 }
 
-static inline void
+static void
 qdio_initialize_set_siga_flags_output(struct qdio_irq *irq_ptr)
 {
        int i;
@@ -2865,7 +2864,7 @@ qdio_initialize_set_siga_flags_output(struct qdio_irq *irq_ptr)
        }
 }
 
-static inline int
+static int
 qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat,
                                    int dstat)
 {
@@ -3014,7 +3013,7 @@ qdio_allocate(struct qdio_initialize *init_data)
        return 0;
 }
 
-int qdio_fill_irq(struct qdio_initialize *init_data)
+static int qdio_fill_irq(struct qdio_initialize *init_data)
 {
        int i;
        char dbf_text[15];
@@ -3367,7 +3366,7 @@ qdio_activate(struct ccw_device *cdev, int flags)
 }
 
 /* buffers filled forwards again to make Rick happy */
-static inline void
+static void
 qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx,
                        unsigned int count, struct qdio_buffer *buffers)
 {
@@ -3386,7 +3385,7 @@ qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx,
        }
 }
 
-static inline void
+static void
 qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx,
                         unsigned int count, struct qdio_buffer *buffers)
 {
@@ -3407,7 +3406,7 @@ qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx,
        }
 }
 
-static inline void
+static void
 do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags,
                       unsigned int qidx, unsigned int count,
                       struct qdio_buffer *buffers)
@@ -3443,7 +3442,7 @@ do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags,
        qdio_mark_q(q);
 }
 
-static inline void
+static void
 do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags,
                        unsigned int qidx, unsigned int count,
                        struct qdio_buffer *buffers)
index 81b5899f4010064b0a3330c82024c2b68527ad17..c7d1355237b668d9342320366b544de205643187 100644 (file)
@@ -465,7 +465,7 @@ static int ap_device_probe(struct device *dev)
  * Flush all requests from the request/pending queue of an AP device.
  * @ap_dev: pointer to the AP device.
  */
-static inline void __ap_flush_queue(struct ap_device *ap_dev)
+static void __ap_flush_queue(struct ap_device *ap_dev)
 {
        struct ap_message *ap_msg, *next;
 
@@ -587,7 +587,7 @@ static struct bus_attribute *const ap_bus_attrs[] = {
 /**
  * Pick one of the 16 ap domains.
  */
-static inline int ap_select_domain(void)
+static int ap_select_domain(void)
 {
        int queue_depth, device_type, count, max_count, best_domain;
        int rc, i, j;
@@ -825,7 +825,7 @@ static inline void ap_schedule_poll_timer(void)
  *        required, bit 2^1 is set if the poll timer needs to get armed
  * Returns 0 if the device is still present, -ENODEV if not.
  */
-static inline int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
+static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
 {
        struct ap_queue_status status;
        struct ap_message *ap_msg;
@@ -872,7 +872,7 @@ static inline int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags)
  *        required, bit 2^1 is set if the poll timer needs to get armed
  * Returns 0 if the device is still present, -ENODEV if not.
  */
-static inline int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
+static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
 {
        struct ap_queue_status status;
        struct ap_message *ap_msg;
index 1edc10a7a6f2d568c9b4a6d715a90c15edb7a424..b9e59bc9435aea3e3c6ad0dea4e903cde728b21a 100644 (file)
@@ -791,7 +791,7 @@ static long trans_xcRB32(struct file *filp, unsigned int cmd,
        return rc;
 }
 
-long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd,
+static long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd,
                         unsigned long arg)
 {
        if (cmd == ICARSAMODEXPO)
@@ -833,8 +833,8 @@ static struct miscdevice zcrypt_misc_device = {
  */
 static struct proc_dir_entry *zcrypt_entry;
 
-static inline int sprintcl(unsigned char *outaddr, unsigned char *addr,
-                          unsigned int len)
+static int sprintcl(unsigned char *outaddr, unsigned char *addr,
+                   unsigned int len)
 {
        int hl, i;
 
@@ -845,8 +845,8 @@ static inline int sprintcl(unsigned char *outaddr, unsigned char *addr,
        return hl;
 }
 
-static inline int sprintrw(unsigned char *outaddr, unsigned char *addr,
-                          unsigned int len)
+static int sprintrw(unsigned char *outaddr, unsigned char *addr,
+                   unsigned int len)
 {
        int hl, inl, c, cx;
 
@@ -865,8 +865,8 @@ static inline int sprintrw(unsigned char *outaddr, unsigned char *addr,
        return hl;
 }
 
-static inline int sprinthx(unsigned char *title, unsigned char *outaddr,
-                          unsigned char *addr, unsigned int len)
+static int sprinthx(unsigned char *title, unsigned char *outaddr,
+                   unsigned char *addr, unsigned int len)
 {
        int hl, inl, r, rx;
 
@@ -885,8 +885,8 @@ static inline int sprinthx(unsigned char *title, unsigned char *outaddr,
        return hl;
 }
 
-static inline int sprinthx4(unsigned char *title, unsigned char *outaddr,
-                           unsigned int *array, unsigned int len)
+static int sprinthx4(unsigned char *title, unsigned char *outaddr,
+                    unsigned int *array, unsigned int len)
 {
        int hl, r;
 
@@ -943,7 +943,7 @@ static int zcrypt_status_read(char *resp_buff, char **start, off_t offset,
        zcrypt_qdepth_mask(workarea);
        len += sprinthx("Waiting work element counts",
                        resp_buff+len, workarea, AP_DEVICES);
-       zcrypt_perdev_reqcnt((unsigned int *) workarea);
+       zcrypt_perdev_reqcnt((int *) workarea);
        len += sprinthx4("Per-device successfully completed request counts",
                         resp_buff+len,(unsigned int *) workarea, AP_DEVICES);
        *eof = 1;
index 32e37014345c60fb02e803d2d25866aeac815fd7..818ffe05ac00b0b02bc53678ffe556b15e318faf 100644 (file)
@@ -191,10 +191,10 @@ static int ICACRT_msg_to_type4CRT_msg(struct zcrypt_device *zdev,
  *
  * Returns 0 on success or -EFAULT.
  */
-static inline int convert_type84(struct zcrypt_device *zdev,
-                                struct ap_message *reply,
-                                char __user *outputdata,
-                                unsigned int outputdatalength)
+static int convert_type84(struct zcrypt_device *zdev,
+                         struct ap_message *reply,
+                         char __user *outputdata,
+                         unsigned int outputdatalength)
 {
        struct type84_hdr *t84h = reply->message;
        char *data;
index b7153c1e15cdea786c2fb7c9d453213aaddda39d..252443b6bd1b5a2d003d360235aaf7de14c1be67 100644 (file)
@@ -709,7 +709,8 @@ out_free:
  *       PCIXCC/CEX2C device to the request distributor
  * @xcRB: pointer to the send_cprb request buffer
  */
-long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB)
+static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
+                                   struct ica_xcRB *xcRB)
 {
        struct ap_message ap_msg;
        struct response_type resp_type = {
index 95f4e105cb969293934538df62228665a7e40d7a..7809a79feec735537d7746043f107662adccb8e2 100644 (file)
@@ -121,7 +121,7 @@ MODULE_LICENSE("GPL");
 #define DEBUG
 #endif
 
- char debug_buffer[255];
+static char debug_buffer[255];
 /**
  * Debug Facility Stuff
  */
@@ -223,16 +223,14 @@ static void claw_timer ( struct chbk * p_ch );
 /* Functions */
 static int add_claw_reads(struct net_device *dev,
        struct ccwbk* p_first, struct ccwbk* p_last);
-static void inline ccw_check_return_code (struct ccw_device *cdev,
-        int return_code);
-static void inline ccw_check_unit_check (struct chbk * p_ch,
-       unsigned char sense );
+static void ccw_check_return_code (struct ccw_device *cdev, int return_code);
+static void ccw_check_unit_check (struct chbk * p_ch, unsigned char sense );
 static int find_link(struct net_device *dev, char *host_name, char *ws_name );
 static int claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid);
 static int init_ccw_bk(struct net_device *dev);
 static void probe_error( struct ccwgroup_device *cgdev);
 static struct net_device_stats *claw_stats(struct net_device *dev);
-static int inline pages_to_order_of_mag(int num_of_pages);
+static int pages_to_order_of_mag(int num_of_pages);
 static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr);
 #ifdef DEBUG
 static void dumpit (char *buf, int len);
@@ -1310,7 +1308,7 @@ claw_timer ( struct chbk * p_ch )
 *    of magnitude get_free_pages() has an upper order of 9           *
 *--------------------------------------------------------------------*/
 
-static int inline
+static int
 pages_to_order_of_mag(int num_of_pages)
 {
        int     order_of_mag=1;         /* assume 2 pages */
@@ -1482,7 +1480,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first,
  *                                                                   *
  *-------------------------------------------------------------------*/
 
-static void inline
+static void
 ccw_check_return_code(struct ccw_device *cdev, int return_code)
 {
 #ifdef FUNCTRACE
@@ -1529,7 +1527,7 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code)
 *       ccw_check_unit_check                                         *
 *--------------------------------------------------------------------*/
 
-static void inline
+static void
 ccw_check_unit_check(struct chbk * p_ch, unsigned char sense )
 {
        struct net_device *dev = p_ch->ndev;
index 03cc263fe0daf6d1e835a6617bbadc69fa297258..5a84fbbc6611de06d3c51ce4a9c98218854e1848 100644 (file)
@@ -369,7 +369,7 @@ ctc_dump_skb(struct sk_buff *skb, int offset)
  * @param ch The channel where this skb has been received.
  * @param pskb The received skb.
  */
-static __inline__ void
+static void
 ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
 {
        struct net_device *dev = ch->netdev;
@@ -512,7 +512,7 @@ ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
  * @param ch          The channel, the error belongs to.
  * @param return_code The error code to inspect.
  */
-static void inline
+static void
 ccw_check_return_code(struct channel *ch, int return_code, char *msg)
 {
        DBF_TEXT(trace, 5, __FUNCTION__);
@@ -547,7 +547,7 @@ ccw_check_return_code(struct channel *ch, int return_code, char *msg)
  * @param ch    The channel, the sense code belongs to.
  * @param sense The sense code to inspect.
  */
-static void inline
+static void
 ccw_unit_check(struct channel *ch, unsigned char sense)
 {
        DBF_TEXT(trace, 5, __FUNCTION__);
@@ -603,7 +603,7 @@ ctc_purge_skb_queue(struct sk_buff_head *q)
        }
 }
 
-static __inline__ int
+static int
 ctc_checkalloc_buffer(struct channel *ch, int warn)
 {
        DBF_TEXT(trace, 5, __FUNCTION__);
index e965f03a7291659a8384998e57eb30748a9b422a..76728ae4b843c669795b346e4b1a1cfb903bd4a1 100644 (file)
@@ -57,7 +57,7 @@ static struct ccw_device_id cu3088_ids[] = {
 
 static struct ccw_driver cu3088_driver;
 
-struct device *cu3088_root_dev;
+static struct device *cu3088_root_dev;
 
 static ssize_t
 group_write(struct device_driver *drv, const char *buf, size_t count)
index e5665b6743a1379d37e949cb549fab52dbb40021..b97dd15bdb9a1ecb7d0b15b3c6ffcbc49ff12200 100644 (file)
@@ -828,7 +828,7 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd)
 /**
  * Emit buffer of a lan comand.
  */
-void
+static void
 lcs_lancmd_timeout(unsigned long data)
 {
        struct lcs_reply *reply, *list_reply, *r;
@@ -1360,7 +1360,7 @@ lcs_get_problem(struct ccw_device *cdev, struct irb *irb)
        return 0;
 }
 
-void
+static void
 lcs_schedule_recovery(struct lcs_card *card)
 {
        LCS_DBF_TEXT(2, trace, "startrec");
@@ -1990,7 +1990,7 @@ lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char
 
 }
 
-DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store);
+static DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store);
 
 static ssize_t
 lcs_dev_recover_store(struct device *dev, struct device_attribute *attr,
index d7d1cc0a5c8e5b7913f71b47244c9460f82b967e..3346088f47e0b6bc2fc708726e2173bc9704493a 100644 (file)
@@ -2053,7 +2053,7 @@ out_free_ndev:
        return ret;
 }
 
-DRIVER_ATTR(connection, 0200, NULL, conn_write);
+static DRIVER_ATTR(connection, 0200, NULL, conn_write);
 
 static ssize_t
 remove_write (struct device_driver *drv, const char *buf, size_t count)
@@ -2112,7 +2112,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count)
         return -EINVAL;
 }
 
-DRIVER_ATTR(remove, 0200, NULL, remove_write);
+static DRIVER_ATTR(remove, 0200, NULL, remove_write);
 
 static void
 netiucv_banner(void)
index 6bb558a9a032870072bec241a6ef724fe9780443..7c735e1fe06377835f508d6abec84d9f7bf09d1d 100644 (file)
@@ -49,7 +49,7 @@ qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue,
        return buffers_needed;
 }
 
-static inline void
+static void
 qeth_eddp_free_context(struct qeth_eddp_context *ctx)
 {
        int i;
@@ -91,7 +91,7 @@ qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
        }
 }
 
-static inline int
+static int
 qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf,
                          struct qeth_eddp_context *ctx)
 {
@@ -196,7 +196,7 @@ out:
        return flush_cnt;
 }
 
-static inline void
+static void
 qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
                              struct qeth_eddp_data *eddp, int data_len)
 {
@@ -256,7 +256,7 @@ qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
        ctx->offset += eddp->thl;
 }
 
-static inline void
+static void
 qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
                        __wsum *hcsum)
 {
@@ -302,7 +302,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
        }
 }
 
-static inline void
+static void
 qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
                                  struct qeth_eddp_data *eddp, int data_len,
                                  __wsum hcsum)
@@ -349,7 +349,7 @@ qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx,
        ((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum);
 }
 
-static inline __wsum
+static __wsum
 qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len)
 {
        __wsum phcsum; /* pseudo header checksum */
@@ -363,7 +363,7 @@ qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len)
        return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum);
 }
 
-static inline __wsum
+static __wsum
 qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len)
 {
        __be32 proto;
@@ -381,7 +381,7 @@ qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len)
        return phcsum;
 }
 
-static inline struct qeth_eddp_data *
+static struct qeth_eddp_data *
 qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl)
 {
        struct qeth_eddp_data *eddp;
@@ -399,7 +399,7 @@ qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl)
        return eddp;
 }
 
-static inline void
+static void
 __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
                             struct qeth_eddp_data *eddp)
 {
@@ -464,7 +464,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
        }
 }
 
-static inline int
+static int
 qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
                           struct sk_buff *skb, struct qeth_hdr *qhdr)
 {
@@ -505,7 +505,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
        return 0;
 }
 
-static inline void
+static void
 qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
                         int hdr_len)
 {
@@ -529,7 +529,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
                            (skb_shinfo(skb)->gso_segs + 1);
 }
 
-static inline struct qeth_eddp_context *
+static struct qeth_eddp_context *
 qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb,
                                 int hdr_len)
 {
@@ -581,7 +581,7 @@ qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb,
        return ctx;
 }
 
-static inline struct qeth_eddp_context *
+static struct qeth_eddp_context *
 qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
                             struct qeth_hdr *qhdr)
 {
@@ -625,5 +625,3 @@ qeth_eddp_create_context(struct qeth_card *card, struct sk_buff *skb,
        }
        return NULL;
 }
-
-
index d2efa5ff125def3fc2ea205165c071a6d43a9c64..2257e45594b3dde36ccebc4a4ee0985f91629025 100644 (file)
@@ -651,7 +651,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo,
                return 0;
 }
 
-static inline int
+static int
 __qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr,
                              int same_type)
 {
@@ -795,7 +795,7 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr)
        return rc;
 }
 
-static inline void
+static void
 __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags)
 {
        struct qeth_ipaddr *addr, *tmp;
@@ -882,7 +882,7 @@ static void qeth_layer2_add_multicast(struct qeth_card *);
 static void qeth_add_multicast_ipv6(struct qeth_card *);
 #endif
 
-static inline int
+static int
 qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread)
 {
        unsigned long flags;
@@ -920,7 +920,7 @@ qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread)
        wake_up(&card->wait_q);
 }
 
-static inline int
+static int
 __qeth_do_run_thread(struct qeth_card *card, unsigned long thread)
 {
        unsigned long flags;
@@ -1764,9 +1764,9 @@ out:
        qeth_release_buffer(channel,iob);
 }
 
-static inline void
+static void
 qeth_prepare_control_data(struct qeth_card *card, int len,
-struct qeth_cmd_buffer *iob)
+                         struct qeth_cmd_buffer *iob)
 {
        qeth_setup_ccw(&card->write,iob->data,len);
        iob->callback = qeth_release_buffer;
@@ -2160,7 +2160,7 @@ qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error,
        return 0;
 }
 
-static inline struct sk_buff *
+static struct sk_buff *
 qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
 {
        struct sk_buff* skb;
@@ -2179,7 +2179,7 @@ qeth_get_skb(unsigned int length, struct qeth_hdr *hdr)
        return skb;
 }
 
-static inline struct sk_buff *
+static struct sk_buff *
 qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
                  struct qdio_buffer_element **__element, int *__offset,
                  struct qeth_hdr **hdr)
@@ -2264,7 +2264,7 @@ no_mem:
        return NULL;
 }
 
-static inline __be16
+static __be16
 qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
        struct qeth_card *card;
@@ -2297,7 +2297,7 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
        return htons(ETH_P_802_2);
 }
 
-static inline void
+static void
 qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
                         struct qeth_hdr *hdr)
 {
@@ -2351,7 +2351,7 @@ qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
        fake_llc->ethertype = ETH_P_IP;
 }
 
-static inline void
+static void
 qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
                         struct qeth_hdr *hdr)
 {
@@ -2420,7 +2420,7 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
        *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
 }
 
-static inline __u16
+static __u16
 qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
                 struct qeth_hdr *hdr)
 {
@@ -2476,7 +2476,7 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
        return vlan_id;
 }
 
-static inline void
+static void
 qeth_process_inbound_buffer(struct qeth_card *card,
                            struct qeth_qdio_buffer *buf, int index)
 {
@@ -2528,7 +2528,7 @@ qeth_process_inbound_buffer(struct qeth_card *card,
        }
 }
 
-static inline struct qeth_buffer_pool_entry *
+static struct qeth_buffer_pool_entry *
 qeth_get_buffer_pool_entry(struct qeth_card *card)
 {
        struct qeth_buffer_pool_entry *entry;
@@ -2543,7 +2543,7 @@ qeth_get_buffer_pool_entry(struct qeth_card *card)
        return NULL;
 }
 
-static inline void
+static void
 qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
 {
        struct qeth_buffer_pool_entry *pool_entry;
@@ -2570,7 +2570,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf)
        buf->state = QETH_QDIO_BUF_EMPTY;
 }
 
-static inline void
+static void
 qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
                         struct qeth_qdio_out_buffer *buf)
 {
@@ -2595,7 +2595,7 @@ qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
        atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
 }
 
-static inline void
+static void
 qeth_queue_input_buffer(struct qeth_card *card, int index)
 {
        struct qeth_qdio_q *queue = card->qdio.in_q;
@@ -2699,7 +2699,7 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
                        card->perf_stats.inbound_start_time;
 }
 
-static inline int
+static int
 qeth_handle_send_error(struct qeth_card *card,
                       struct qeth_qdio_out_buffer *buffer,
                       unsigned int qdio_err, unsigned int siga_err)
@@ -2821,7 +2821,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
  * Switched to packing state if the number of used buffers on a queue
  * reaches a certain limit.
  */
-static inline void
+static void
 qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
 {
        if (!queue->do_pack) {
@@ -2842,7 +2842,7 @@ qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
  * In that case 1 is returned to inform the caller. If no buffer
  * has to be flushed, zero is returned.
  */
-static inline int
+static int
 qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
 {
        struct qeth_qdio_out_buffer *buffer;
@@ -2877,7 +2877,7 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
  * Checks if there is a packing buffer and prepares it to be flushed.
  * In that case returns 1, otherwise zero.
  */
-static inline int
+static int
 qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
 {
        struct qeth_qdio_out_buffer *buffer;
@@ -2894,7 +2894,7 @@ qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue)
        return 0;
 }
 
-static inline void
+static void
 qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
 {
        int index;
@@ -3594,7 +3594,7 @@ qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
        }
 }
 
-static inline int
+static int
 qeth_send_packet(struct qeth_card *, struct sk_buff *);
 
 static int
@@ -3759,7 +3759,7 @@ qeth_stop(struct net_device *dev)
        return 0;
 }
 
-static inline int
+static int
 qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
 {
        int cast_type = RTN_UNSPEC;
@@ -3806,7 +3806,7 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
        return cast_type;
 }
 
-static inline int
+static int
 qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
                        int ipv, int cast_type)
 {
@@ -3853,7 +3853,7 @@ qeth_get_ip_version(struct sk_buff *skb)
        }
 }
 
-static inline struct qeth_hdr *
+static struct qeth_hdr *
 __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
 {
 #ifdef CONFIG_QETH_VLAN
@@ -3882,14 +3882,14 @@ __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv)
                qeth_push_skb(card, skb, sizeof(struct qeth_hdr)));
 }
 
-static inline void
+static void
 __qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb)
 {
        if (orig_skb != new_skb)
                dev_kfree_skb_any(new_skb);
 }
 
-static inline struct sk_buff *
+static struct sk_buff *
 qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb,
                 struct qeth_hdr **hdr, int ipv)
 {
@@ -3940,7 +3940,7 @@ qeth_get_qeth_hdr_flags6(int cast_type)
        return ct | QETH_CAST_UNICAST;
 }
 
-static inline void
+static void
 qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr,
                            struct sk_buff *skb)
 {
@@ -3977,7 +3977,7 @@ qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr,
        }
 }
 
-static inline void
+static void
 qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
                        struct sk_buff *skb, int cast_type)
 {
@@ -4068,7 +4068,7 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
        }
 }
 
-static inline void
+static void
 __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
                   int is_tso, int *next_element_to_fill)
 {
@@ -4112,7 +4112,7 @@ __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
        *next_element_to_fill = element;
 }
 
-static inline int
+static int
 qeth_fill_buffer(struct qeth_qdio_out_q *queue,
                 struct qeth_qdio_out_buffer *buf,
                 struct sk_buff *skb)
@@ -4171,7 +4171,7 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue,
        return flush_cnt;
 }
 
-static inline int
+static int
 qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue,
                         struct sk_buff *skb, struct qeth_hdr *hdr,
                         int elements_needed,
@@ -4222,7 +4222,7 @@ out:
        return -EBUSY;
 }
 
-static inline int
+static int
 qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue,
                    struct sk_buff *skb, struct qeth_hdr *hdr,
                    int elements_needed, struct qeth_eddp_context *ctx)
@@ -4328,7 +4328,7 @@ out:
        return rc;
 }
 
-static inline int
+static int
 qeth_get_elements_no(struct qeth_card *card, void *hdr,
                     struct sk_buff *skb, int elems)
 {
@@ -4349,7 +4349,7 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr,
 }
 
 
-static inline int
+static int
 qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
 {
        int ipv = 0;
@@ -4536,7 +4536,7 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)
 }
 
 
-static inline const char *
+static const char *
 qeth_arp_get_error_cause(int *rc)
 {
        switch (*rc) {
@@ -4597,7 +4597,7 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries)
        return rc;
 }
 
-static inline void
+static void
 qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo,
                               struct qeth_arp_query_data *qdata,
                               int entry_size, int uentry_size)
@@ -5214,7 +5214,7 @@ qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
        spin_unlock_irqrestore(&card->vlanlock, flags);
 }
 
-static inline void
+static void
 qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf,
                      unsigned short vid)
 {
@@ -5625,7 +5625,7 @@ qeth_delete_mc_addresses(struct qeth_card *card)
        spin_unlock_irqrestore(&card->ip_lock, flags);
 }
 
-static inline void
+static void
 qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev)
 {
        struct qeth_ipaddr *ipm;
@@ -5711,7 +5711,7 @@ qeth_layer2_add_multicast(struct qeth_card *card)
 }
 
 #ifdef CONFIG_QETH_IPV6
-static inline void
+static void
 qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev)
 {
        struct qeth_ipaddr *ipm;
@@ -6022,7 +6022,7 @@ qeth_send_setdelmc(struct qeth_card *card, struct qeth_ipaddr *addr, int ipacmd)
 
        return rc;
 }
-static inline void
+static void
 qeth_fill_netmask(u8 *netmask, unsigned int len)
 {
        int i,j;
@@ -6626,7 +6626,7 @@ qeth_send_setadp_mode(struct qeth_card *card, __u32 command, __u32 mode)
        return rc;
 }
 
-static inline int
+static int
 qeth_setadapter_hstr(struct qeth_card *card)
 {
        int rc;
@@ -6889,7 +6889,7 @@ qeth_send_simple_setassparms(struct qeth_card *card,
        return rc;
 }
 
-static inline int
+static int
 qeth_start_ipa_arp_processing(struct qeth_card *card)
 {
        int rc;
@@ -7529,7 +7529,7 @@ qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
        wake_up(&card->wait_q);
 }
 
-static inline int
+static int
 qeth_threads_running(struct qeth_card *card, unsigned long threads)
 {
        unsigned long flags;
@@ -8118,7 +8118,7 @@ qeth_del_ipato_entry(struct qeth_card *card, enum qeth_prot_versions proto,
        spin_unlock_irqrestore(&card->ip_lock, flags);
 }
 
-static inline void
+static void
 qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len)
 {
        int i, j;
index 5836737ac58f26157f8d21d54c9ec1bd0723e07b..d518419cd0c6389bd966fab970fc6768f76f98b6 100644 (file)
@@ -328,7 +328,7 @@ qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const c
 static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
                qeth_dev_bufcnt_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route,
                    char *buf)
 {
@@ -368,7 +368,7 @@ qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *bu
        return qeth_dev_route_show(card, &card->options.route4, buf);
 }
 
-static inline ssize_t
+static ssize_t
 qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route,
                enum qeth_prot_versions prot, const char *buf, size_t count)
 {
@@ -998,7 +998,7 @@ struct device_attribute dev_attr_##_id = {                               \
        .store  = _store,                                                    \
 };
 
-int
+static int
 qeth_check_layer2(struct qeth_card *card)
 {
        if (card->options.layer2)
@@ -1100,7 +1100,7 @@ static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
                        qeth_dev_ipato_invert4_show,
                        qeth_dev_ipato_invert4_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
                        enum qeth_prot_versions proto)
 {
@@ -1146,7 +1146,7 @@ qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char
        return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4);
 }
 
-static inline int
+static int
 qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
                  u8 *addr, int *mask_bits)
 {
@@ -1178,7 +1178,7 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto,
        return 0;
 }
 
-static inline ssize_t
+static ssize_t
 qeth_dev_ipato_add_store(const char *buf, size_t count,
                         struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1223,7 +1223,7 @@ static QETH_DEVICE_ATTR(ipato_add4, add4, 0644,
                        qeth_dev_ipato_add4_show,
                        qeth_dev_ipato_add4_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_ipato_del_store(const char *buf, size_t count,
                         struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1361,7 +1361,7 @@ static struct attribute_group qeth_device_ipato_group = {
        .attrs = (struct attribute **)qeth_ipato_device_attrs,
 };
 
-static inline ssize_t
+static ssize_t
 qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
                        enum qeth_prot_versions proto)
 {
@@ -1407,7 +1407,7 @@ qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char
        return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4);
 }
 
-static inline int
+static int
 qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto,
                 u8 *addr)
 {
@@ -1418,7 +1418,7 @@ qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto,
        return 0;
 }
 
-static inline ssize_t
+static ssize_t
 qeth_dev_vipa_add_store(const char *buf, size_t count,
                         struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1451,7 +1451,7 @@ static QETH_DEVICE_ATTR(vipa_add4, add4, 0644,
                        qeth_dev_vipa_add4_show,
                        qeth_dev_vipa_add4_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_vipa_del_store(const char *buf, size_t count,
                         struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1542,7 +1542,7 @@ static struct attribute_group qeth_device_vipa_group = {
        .attrs = (struct attribute **)qeth_vipa_device_attrs,
 };
 
-static inline ssize_t
+static ssize_t
 qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
                       enum qeth_prot_versions proto)
 {
@@ -1588,7 +1588,7 @@ qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char
        return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4);
 }
 
-static inline int
+static int
 qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto,
                 u8 *addr)
 {
@@ -1599,7 +1599,7 @@ qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto,
        return 0;
 }
 
-static inline ssize_t
+static ssize_t
 qeth_dev_rxip_add_store(const char *buf, size_t count,
                        struct qeth_card *card, enum qeth_prot_versions proto)
 {
@@ -1632,7 +1632,7 @@ static QETH_DEVICE_ATTR(rxip_add4, add4, 0644,
                        qeth_dev_rxip_add4_show,
                        qeth_dev_rxip_add4_store);
 
-static inline ssize_t
+static ssize_t
 qeth_dev_rxip_del_store(const char *buf, size_t count,
                        struct qeth_card *card, enum qeth_prot_versions proto)
 {
index e088b5e287111b7268e322ad62dc838663d4815c..806bb1a921eb99e83822a9b2668ba150b26eecf3 100644 (file)
 #include <linux/errno.h>
 #include <linux/workqueue.h>
 #include <linux/time.h>
+#include <linux/device.h>
 #include <linux/kthread.h>
-
+#include <asm/etr.h>
 #include <asm/lowcore.h>
-
+#include <asm/cio.h>
+#include "cio/cio.h"
+#include "cio/chsc.h"
+#include "cio/css.h"
 #include "s390mach.h"
 
 static struct semaphore m_sem;
 
-extern int css_process_crw(int, int);
-extern int chsc_process_crw(void);
-extern int chp_process_crw(int, int);
-extern void css_reiterate_subchannels(void);
-
-extern struct workqueue_struct *slow_path_wq;
-extern struct work_struct slow_path_work;
-
 static NORET_TYPE void
 s390_handle_damage(char *msg)
 {
@@ -470,6 +466,19 @@ s390_do_machine_check(struct pt_regs *regs)
                        s390_handle_damage("unable to revalidate registers.");
        }
 
+       if (mci->cd) {
+               /* Timing facility damage */
+               s390_handle_damage("TOD clock damaged");
+       }
+
+       if (mci->ed && mci->ec) {
+               /* External damage */
+               if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC))
+                       etr_sync_check();
+               if (S390_lowcore.external_damage_code & (1U << ED_ETR_SWITCH))
+                       etr_switch_to_local();
+       }
+
        if (mci->se)
                /* Storage error uncorrected */
                s390_handle_damage("received storage error uncorrected "
@@ -508,7 +517,7 @@ static int
 machine_check_init(void)
 {
        init_MUTEX_LOCKED(&m_sem);
-       ctl_clear_bit(14, 25);  /* disable external damage MCH */
+       ctl_set_bit(14, 25);    /* enable external damage MCH */
        ctl_set_bit(14, 27);    /* enable system recovery MCH */
 #ifdef CONFIG_MACHCHK_WARNING
        ctl_set_bit(14, 24);    /* enable warning MCH */
@@ -529,7 +538,11 @@ arch_initcall(machine_check_init);
 static int __init
 machine_check_crw_init (void)
 {
-       kthread_run(s390_collect_crw_info, &m_sem, "kmcheck");
+       struct task_struct *task;
+
+       task = kthread_run(s390_collect_crw_info, &m_sem, "kmcheck");
+       if (IS_ERR(task))
+               return PTR_ERR(task);
        ctl_set_bit(14, 28);    /* enable channel report MCH */
        return 0;
 }
index 7abb42a09ae2e9a162123fc45fceda10500994d8..d3ca4281a494affcf21bbd04d62ffe086a2915da 100644 (file)
@@ -102,4 +102,7 @@ static inline int stcrw(struct crw *pcrw )
        return ccode;
 }
 
+#define ED_ETR_SYNC    12      /* External damage ETR sync check */
+#define ED_ETR_SWITCH  13      /* External damage ETR switch to local */
+
 #endif /* __s390mach */
index 85093b71f9fa52ebc9f0f95716c16f840111a926..39a8852667909b3d0c57e282f9b0ae72bf46078d 100644 (file)
@@ -47,13 +47,12 @@ static int __init  zfcp_module_init(void);
 static void zfcp_ns_gid_pn_handler(unsigned long);
 
 /* miscellaneous */
-static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
-static inline void zfcp_sg_list_free(struct zfcp_sg_list *);
-static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
-                                             void __user *, size_t);
-static inline int zfcp_sg_list_copy_to_user(void __user *,
-                                           struct zfcp_sg_list *, size_t);
-
+static int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
+static void zfcp_sg_list_free(struct zfcp_sg_list *);
+static int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
+                                      void __user *, size_t);
+static int zfcp_sg_list_copy_to_user(void __user *,
+                                    struct zfcp_sg_list *, size_t);
 static long zfcp_cfdc_dev_ioctl(struct file *, unsigned int, unsigned long);
 
 #define ZFCP_CFDC_IOC_MAGIC                     0xDD
@@ -605,7 +604,7 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
  * elements of the scatter-gather list. The maximum size of a single element
  * in the scatter-gather list is PAGE_SIZE.
  */
-static inline int
+static int
 zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
 {
        struct scatterlist *sg;
@@ -652,7 +651,7 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
  * Memory for each element in the scatter-gather list is freed.
  * Finally sg_list->sg is freed itself and sg_list->count is reset.
  */
-static inline void
+static void
 zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
 {
        struct scatterlist *sg;
@@ -697,7 +696,7 @@ zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
  * @size: number of bytes to be copied
  * Return: 0 on success, -EFAULT if copy_from_user fails.
  */
-static inline int
+static int
 zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
                            void __user *user_buffer,
                             size_t size)
@@ -735,7 +734,7 @@ zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
  * @size: number of bytes to be copied
  * Return: 0 on success, -EFAULT if copy_to_user fails
  */
-static inline int
+static int
 zfcp_sg_list_copy_to_user(void __user  *user_buffer,
                          struct zfcp_sg_list *sg_list,
                           size_t size)
@@ -1799,7 +1798,7 @@ static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = {
  * @code: reason code
  * @rc_table: table of reason codes and descriptions
  */
-static inline const char *
+static const char *
 zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table)
 {
        const char *descr = "unknown reason code";
@@ -1847,7 +1846,7 @@ zfcp_check_ct_response(struct ct_hdr *rjt)
  * @rjt_par: reject parameter acc. to FC-PH/FC-FS
  * @rc_table: table of reason codes and descriptions
  */
-static inline void
+static void
 zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par,
                   const struct zfcp_rc_entry *rc_table)
 {
index 0aa3b1ac76af4e66c8fd249c0c36624e8fa4fea2..d8191d115c14a3c8a8db329f5613e53bc2805224 100644 (file)
@@ -31,7 +31,7 @@ MODULE_PARM_DESC(dbfsize,
 
 #define ZFCP_LOG_AREA                  ZFCP_LOG_AREA_OTHER
 
-static inline int
+static int
 zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck)
 {
        unsigned long long sec;
@@ -106,7 +106,7 @@ zfcp_dbf_view_dump(char *out_buf, const char *label,
        return len;
 }
 
-static inline int
+static int
 zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
                     debug_entry_t * entry, char *out_buf)
 {
@@ -130,7 +130,7 @@ zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area,
        return len;
 }
 
-inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
+void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_adapter *adapter = fsf_req->adapter;
        struct fsf_qtcb *qtcb = fsf_req->qtcb;
@@ -241,7 +241,7 @@ inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req)
        spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
 }
 
-inline void
+void
 zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
                             struct fsf_status_read_buffer *status_buffer)
 {
@@ -295,7 +295,7 @@ zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter,
        spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
 }
 
-inline void
+void
 zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
                        unsigned int qdio_error, unsigned int siga_error,
                        int sbal_index, int sbal_count)
@@ -316,7 +316,7 @@ zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status,
        spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags);
 }
 
-static inline int
+static int
 zfcp_hba_dbf_view_response(char *out_buf,
                           struct zfcp_hba_dbf_record_response *rec)
 {
@@ -403,7 +403,7 @@ zfcp_hba_dbf_view_response(char *out_buf,
        return len;
 }
 
-static inline int
+static int
 zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
 {
        int len = 0;
@@ -424,7 +424,7 @@ zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec)
        return len;
 }
 
-static inline int
+static int
 zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec)
 {
        int len = 0;
@@ -469,7 +469,7 @@ zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view,
        return len;
 }
 
-struct debug_view zfcp_hba_dbf_view = {
+static struct debug_view zfcp_hba_dbf_view = {
        "structured",
        NULL,
        &zfcp_dbf_view_header,
@@ -478,7 +478,7 @@ struct debug_view zfcp_hba_dbf_view = {
        NULL
 };
 
-inline void
+void
 _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
                              u32 s_id, u32 d_id, void *buffer, int buflen)
 {
@@ -519,7 +519,7 @@ _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
        spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
 }
 
-inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
        struct zfcp_port *port = ct->port;
@@ -531,7 +531,7 @@ inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req)
                                      ct->req->length);
 }
 
-inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data;
        struct zfcp_port *port = ct->port;
@@ -543,7 +543,7 @@ inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req)
                                      ct->resp->length);
 }
 
-static inline void
+static void
 _zfcp_san_dbf_event_common_els(const char *tag, int level,
                               struct zfcp_fsf_req *fsf_req, u32 s_id,
                               u32 d_id, u8 ls_code, void *buffer, int buflen)
@@ -585,7 +585,7 @@ _zfcp_san_dbf_event_common_els(const char *tag, int level,
        spin_unlock_irqrestore(&adapter->san_dbf_lock, flags);
 }
 
-inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
 
@@ -597,7 +597,7 @@ inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req)
                                       els->req->length);
 }
 
-inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data;
 
@@ -608,7 +608,7 @@ inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req)
                                       els->resp->length);
 }
 
-inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
+void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req)
 {
        struct zfcp_adapter *adapter = fsf_req->adapter;
        struct fsf_status_read_buffer *status_buffer =
@@ -693,7 +693,7 @@ zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view,
        return len;
 }
 
-struct debug_view zfcp_san_dbf_view = {
+static struct debug_view zfcp_san_dbf_view = {
        "structured",
        NULL,
        &zfcp_dbf_view_header,
@@ -702,7 +702,7 @@ struct debug_view zfcp_san_dbf_view = {
        NULL
 };
 
-static inline void
+static void
 _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
                            struct zfcp_adapter *adapter,
                            struct scsi_cmnd *scsi_cmnd,
@@ -786,7 +786,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level,
        spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags);
 }
 
-inline void
+void
 zfcp_scsi_dbf_event_result(const char *tag, int level,
                           struct zfcp_adapter *adapter,
                           struct scsi_cmnd *scsi_cmnd,
@@ -796,7 +796,7 @@ zfcp_scsi_dbf_event_result(const char *tag, int level,
                        adapter, scsi_cmnd, fsf_req, 0);
 }
 
-inline void
+void
 zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
                          struct scsi_cmnd *scsi_cmnd,
                          struct zfcp_fsf_req *new_fsf_req,
@@ -806,7 +806,7 @@ zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter,
                        adapter, scsi_cmnd, new_fsf_req, old_req_id);
 }
 
-inline void
+void
 zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit,
                             struct scsi_cmnd *scsi_cmnd)
 {
@@ -884,7 +884,7 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view,
        return len;
 }
 
-struct debug_view zfcp_scsi_dbf_view = {
+static struct debug_view zfcp_scsi_dbf_view = {
        "structured",
        NULL,
        &zfcp_dbf_view_header,
index c88babce9bca813117249eb45f87a5960bdfe76c..88642dec080c086e36023dcd6ffc877032d3e63e 100644 (file)
@@ -200,7 +200,7 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
  * returns:    0       - initiated action successfully
  *             <0      - failed to initiate action
  */
-int
+static int
 zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask)
 {
        int retval;
@@ -295,7 +295,7 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
  * zfcp_erp_adisc - send ADISC ELS command
  * @port: port structure
  */
-int
+static int
 zfcp_erp_adisc(struct zfcp_port *port)
 {
        struct zfcp_adapter *adapter = port->adapter;
@@ -380,7 +380,7 @@ zfcp_erp_adisc(struct zfcp_port *port)
  *
  * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered.
  */
-void
+static void
 zfcp_erp_adisc_handler(unsigned long data)
 {
        struct zfcp_send_els *send_els;
@@ -3141,7 +3141,6 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
                break;
        case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
                if (result != ZFCP_ERP_SUCCEEDED) {
-                       struct zfcp_port *port;
                        list_for_each_entry(port, &adapter->port_list_head, list)
                                if (port->rport &&
                                    !atomic_test_mask(ZFCP_STATUS_PORT_WKA,
index b8794d77285dde41018bbce1ea00c8bc3dcd4609..cda0cc095ad1bb9b862d7c9049a17d76dc38807b 100644 (file)
@@ -119,8 +119,8 @@ extern int  zfcp_adapter_scsi_register(struct zfcp_adapter *);
 extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
 extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t);
 extern char *zfcp_get_fcp_rsp_info_ptr(struct fcp_rsp_iu *);
-extern void set_host_byte(u32 *, char);
-extern void set_driver_byte(u32 *, char);
+extern void set_host_byte(int *, char);
+extern void set_driver_byte(int *, char);
 extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
 extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *);
 
index 067f1519eb04dcda87ff07f79d6cae072675770e..4b3ae3f22e78c448c21d28318adf3726e95c8c28 100644 (file)
@@ -4563,7 +4563,7 @@ zfcp_fsf_req_sbal_check(unsigned long *flags,
 /*
  * set qtcb pointer in fsf_req and initialize QTCB
  */
-static inline void
+static void
 zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req)
 {
        if (likely(fsf_req->qtcb != NULL)) {
index dbd9f48e863eee678df9a6a9762f54d4a0bbd887..1e12a78e8edd1c17886a66f5e7bf2b530adf6018 100644 (file)
 
 #include "zfcp_ext.h"
 
-static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int);
+static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int);
 static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_get
        (struct zfcp_qdio_queue *, int, int);
 static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_resp
        (struct zfcp_fsf_req *, int, int);
-static inline volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain
+static volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain
        (struct zfcp_fsf_req *, unsigned long);
-static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_next
+static volatile struct qdio_buffer_element *zfcp_qdio_sbale_next
        (struct zfcp_fsf_req *, unsigned long);
-static inline int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int);
+static int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int);
 static inline int zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *);
-static inline void zfcp_qdio_sbale_fill
+static void zfcp_qdio_sbale_fill
        (struct zfcp_fsf_req *, unsigned long, void *, int);
-static inline int zfcp_qdio_sbals_from_segment
+static int zfcp_qdio_sbals_from_segment
        (struct zfcp_fsf_req *, unsigned long, void *, unsigned long);
-static inline int zfcp_qdio_sbals_from_buffer
+static int zfcp_qdio_sbals_from_buffer
        (struct zfcp_fsf_req *, unsigned long, void *, unsigned long, int);
 
 static qdio_handler_t zfcp_qdio_request_handler;
@@ -201,7 +201,7 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter)
  * returns:    error flag
  *
  */
-static inline int
+static int
 zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
                              unsigned int qdio_error, unsigned int siga_error,
                              int first_element, int elements_processed)
@@ -462,7 +462,7 @@ zfcp_qdio_sbale_get(struct zfcp_qdio_queue *queue, int sbal, int sbale)
  * zfcp_qdio_sbale_req - return pointer to SBALE of request_queue for
  *     a struct zfcp_fsf_req
  */
-inline volatile struct qdio_buffer_element *
+volatile struct qdio_buffer_element *
 zfcp_qdio_sbale_req(struct zfcp_fsf_req *fsf_req, int sbal, int sbale)
 {
        return zfcp_qdio_sbale_get(&fsf_req->adapter->request_queue,
@@ -484,7 +484,7 @@ zfcp_qdio_sbale_resp(struct zfcp_fsf_req *fsf_req, int sbal, int sbale)
  * zfcp_qdio_sbale_curr - return current SBALE on request_queue for
  *     a struct zfcp_fsf_req
  */
-inline volatile struct qdio_buffer_element *
+volatile struct qdio_buffer_element *
 zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req)
 {
        return zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr,
@@ -499,7 +499,7 @@ zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req)
  *
  * Note: We can assume at least one free SBAL in the request_queue when called.
  */
-static inline void
+static void
 zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
 {
        int count = atomic_read(&fsf_req->adapter->request_queue.free_count);
@@ -517,7 +517,7 @@ zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
  *
  * This function changes sbal_curr, sbale_curr, sbal_number of fsf_req.
  */
-static inline volatile struct qdio_buffer_element *
+static volatile struct qdio_buffer_element *
 zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
 {
        volatile struct qdio_buffer_element *sbale;
@@ -554,7 +554,7 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
 /**
  * zfcp_qdio_sbale_next - switch to next SBALE, chain SBALs if needed
  */
-static inline volatile struct qdio_buffer_element *
+static volatile struct qdio_buffer_element *
 zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
 {
        if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
@@ -569,7 +569,7 @@ zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
  * zfcp_qdio_sbals_zero - initialize SBALs between first and last in queue
  *     with zero from
  */
-static inline int
+static int
 zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *queue, int first, int last)
 {
        struct qdio_buffer **buf = queue->buffer;
@@ -603,7 +603,7 @@ zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *fsf_req)
  * zfcp_qdio_sbale_fill - set address and lenght in current SBALE
  *     on request_queue
  */
-static inline void
+static void
 zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
                     void *addr, int length)
 {
@@ -624,7 +624,7 @@ zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
  * Alignment and length of the segment determine how many SBALEs are needed
  * for the memory segment.
  */
-static inline int
+static int
 zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
                             void *start_addr, unsigned long total_length)
 {
@@ -659,7 +659,7 @@ zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
  * @sg_count: number of elements in scatter-gather list
  * @max_sbals: upper bound for number of SBALs to be used
  */
-inline int
+int
 zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
                         struct scatterlist *sg,        int sg_count, int max_sbals)
 {
@@ -707,7 +707,7 @@ out:
  * @length: length of buffer
  * @max_sbals: upper bound for number of SBALs to be used
  */
-static inline int
+static int
 zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
                            void *buffer, unsigned long length, int max_sbals)
 {
@@ -728,7 +728,7 @@ zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
  * @scsi_cmnd: either scatter-gather list or buffer contained herein is used
  *     to fill SBALs
  */
-inline int
+int
 zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req,
                              unsigned long sbtype, struct scsi_cmnd *scsi_cmnd)
 {
index 452d96f92a1482a5611a79e5712a2c53f04d31ad..99db02062c3b4af325e8cbfa3b9208d333a867d5 100644 (file)
@@ -90,7 +90,7 @@ zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu)
        return fcp_sns_info_ptr;
 }
 
-fcp_dl_t *
+static fcp_dl_t *
 zfcp_get_fcp_dl_ptr(struct fcp_cmnd_iu * fcp_cmd)
 {
        int additional_length = fcp_cmd->add_fcp_cdb_length << 2;
@@ -124,19 +124,19 @@ zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, fcp_dl_t fcp_dl)
  * regarding the specified byte
  */
 static inline void
-set_byte(u32 * result, char status, char pos)
+set_byte(int *result, char status, char pos)
 {
        *result |= status << (pos * 8);
 }
 
 void
-set_host_byte(u32 * result, char status)
+set_host_byte(int *result, char status)
 {
        set_byte(result, status, 2);
 }
 
 void
-set_driver_byte(u32 * result, char status)
+set_driver_byte(int *result, char status)
 {
        set_byte(result, status, 3);
 }
@@ -280,7 +280,7 @@ out:
        return retval;
 }
 
-void
+static void
 zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt)
 {
        struct completion *wait = (struct completion *) scpnt->SCp.ptr;
@@ -324,7 +324,7 @@ zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt,
  * returns:    0 - success, SCSI command enqueued
  *             !0 - failure
  */
-int
+static int
 zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt,
                       void (*done) (struct scsi_cmnd *))
 {
@@ -380,7 +380,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id,
  * will handle late commands.  (Usually, the normal completion of late
  * commands is ignored with respect to the running abort operation.)
  */
-int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 {
        struct Scsi_Host *scsi_host;
        struct zfcp_adapter *adapter;
@@ -445,7 +445,7 @@ int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        return retval;
 }
 
-int
+static int
 zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
 {
        int retval;
@@ -541,7 +541,7 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags,
 /**
  * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset
  */
-int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
+static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 {
        struct zfcp_unit *unit;
        struct zfcp_adapter *adapter;
index 1e788e815ce7f872f629a91d75936f446f1835c8..090743d2f914aec39990cdca66f40455df512450 100644 (file)
@@ -9,8 +9,14 @@
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <asm/ebcdic.h>
 
+/* Sigh, math-emu. Don't ask. */
+#include <asm/sfp-util.h>
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+
 struct sysinfo_1_1_1 {
        char reserved_0[32];
        char manufacturer[16];
@@ -198,7 +204,7 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len)
                 * if the higher order 8 bits are not zero. Printing
                 * a floating point number in the kernel is a no-no,
                 * always print the number as 32 bit unsigned integer.
-                * The user-space needs to know about the stange
+                * The user-space needs to know about the strange
                 * encoding of the alternate cpu capability.
                 */
                len += sprintf(page + len, "Capability:           %u %u\n",
@@ -351,3 +357,58 @@ static __init int create_proc_sysinfo(void)
 
 __initcall(create_proc_sysinfo);
 
+/*
+ * CPU capability might have changed. Therefore recalculate loops_per_jiffy.
+ */
+void s390_adjust_jiffies(void)
+{
+       struct sysinfo_1_2_2 *info;
+       const unsigned int fmil = 0x4b189680;   /* 1e7 as 32-bit float. */
+       FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
+       FP_DECL_EX;
+       unsigned int capability;
+
+       info = (void *) get_zeroed_page(GFP_KERNEL);
+       if (!info)
+               return;
+
+       if (stsi(info, 1, 2, 2) != -ENOSYS) {
+               /*
+                * Major sigh. The cpu capability encoding is "special".
+                * If the first 9 bits of info->capability are 0 then it
+                * is a 32 bit unsigned integer in the range 0 .. 2^23.
+                * If the first 9 bits are != 0 then it is a 32 bit float.
+                * In addition a lower value indicates a proportionally
+                * higher cpu capacity. Bogomips are the other way round.
+                * To get to a halfway suitable number we divide 1e7
+                * by the cpu capability number. Yes, that means a floating
+                * point division .. math-emu here we come :-)
+                */
+               FP_UNPACK_SP(SA, &fmil);
+               if ((info->capability >> 23) == 0)
+                       FP_FROM_INT_S(SB, info->capability, 32, int);
+               else
+                       FP_UNPACK_SP(SB, &info->capability);
+               FP_DIV_S(SR, SA, SB);
+               FP_TO_INT_S(capability, SR, 32, 0);
+       } else
+               /*
+                * Really old machine without stsi block for basic
+                * cpu information. Report 42.0 bogomips.
+                */
+               capability = 42;
+       loops_per_jiffy = capability * (500000/HZ);
+       free_page((unsigned long) info);
+}
+
+/*
+ * calibrate the delay loop
+ */
+void __init calibrate_delay(void)
+{
+       s390_adjust_jiffies();
+       /* Print the good old Bogomips line .. */
+       printk(KERN_DEBUG "Calibrating delay loop (skipped)... "
+              "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ),
+              (loops_per_jiffy/(5000/HZ)) % 100);
+}
index c7d887540d8d506db46ea65780e090910f28ea25..aa6a620c162f5f8bcaaeada2b8aa995165c38604 100644 (file)
@@ -69,6 +69,14 @@ config LOGITECH_FF
          Note: if you say N here, this device will still be supported, but without
          force feedback.
 
+config PANTHERLORD_FF
+       bool "PantherLord USB/PS2 2in1 Adapter support"
+       depends on HID_FF
+       select INPUT_FF_MEMLESS if USB_HID
+       help
+         Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want
+         to enable force feedback support for it.
+
 config THRUSTMASTER_FF
        bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)"
        depends on HID_FF && EXPERIMENTAL
index 1a24b5bfa05fcd493adecc2822e3aab0fe862c62..a06024e5cd562ef647e0e3123231a37a7b99bab5 100644 (file)
@@ -17,6 +17,9 @@ endif
 ifeq ($(CONFIG_LOGITECH_FF),y)
        usbhid-objs     += hid-lgff.o
 endif
+ifeq ($(CONFIG_PANTHERLORD_FF),y)
+       usbhid-objs     += hid-plff.o
+endif
 ifeq ($(CONFIG_THRUSTMASTER_FF),y)
        usbhid-objs     += hid-tmff.o
 endif
index c6c9e72e5fd9d94a3fada3216e41090b907815d0..e07a304907260c19df9688d32351a19b4df8cb8f 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <linux/hid.h>
 #include <linux/hiddev.h>
+#include <linux/hid-debug.h>
 #include "usbhid.h"
 
 /*
@@ -220,23 +221,6 @@ static void hid_irq_in(struct urb *urb)
        }
 }
 
-/*
- * Find a report field with a specified HID usage.
- */
-#if 0
-struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type)
-{
-       struct hid_report *report;
-       int i;
-
-       list_for_each_entry(report, &hid->report_enum[type].report_list, list)
-               for (i = 0; i < report->maxfield; i++)
-                       if (report->field[i]->logical == wanted_usage)
-                               return report->field[i];
-       return NULL;
-}
-#endif  /*  0  */
-
 static int hid_submit_out(struct hid_device *hid)
 {
        struct hid_report *report;
@@ -501,7 +485,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
 {
        int result, retries = 4;
 
-       memset(buf,0,size);     // Make sure we parse really received data
+       memset(buf, 0, size);
 
        do {
                result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
@@ -528,18 +512,6 @@ void usbhid_close(struct hid_device *hid)
                usb_kill_urb(usbhid->urbin);
 }
 
-static int hidinput_open(struct input_dev *dev)
-{
-       struct hid_device *hid = dev->private;
-       return usbhid_open(hid);
-}
-
-static void hidinput_close(struct input_dev *dev)
-{
-       struct hid_device *hid = dev->private;
-       usbhid_close(hid);
-}
-
 #define USB_VENDOR_ID_PANJIT           0x134c
 
 #define USB_VENDOR_ID_TURBOX           0x062a
@@ -770,6 +742,7 @@ void usbhid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_APPLE_GEYSER4_JIS        0x021c
 #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY   0x030a
 #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY    0x030b
+#define USB_DEVICE_ID_APPLE_IR         0x8240
 
 #define USB_VENDOR_ID_CHERRY           0x046a
 #define USB_DEVICE_ID_CHERRY_CYMOTION  0x0023
@@ -792,6 +765,9 @@ void usbhid_init_reports(struct hid_device *hid)
 #define USB_VENDOR_ID_IMATION          0x0718
 #define USB_DEVICE_ID_DISC_STAKKA      0xd000
 
+#define USB_VENDOR_ID_PANTHERLORD      0x0810
+#define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK    0x0001
+
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -946,19 +922,21 @@ static const struct hid_blacklist {
 
        { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
 
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
-       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+
+       { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR, HID_QUIRK_IGNORE },
 
        { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
@@ -969,6 +947,8 @@ static const struct hid_blacklist {
 
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
 
+       { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
+
        { 0, 0 }
 };
 
@@ -1064,6 +1044,11 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        if (quirks & HID_QUIRK_IGNORE)
                return NULL;
 
+       if ((quirks & HID_QUIRK_IGNORE_MOUSE) &&
+               (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE))
+                       return NULL;
+
+
        if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
            (!interface->desc.bNumEndpoints ||
             usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
@@ -1235,8 +1220,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
        usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
        hid->hidinput_input_event = usb_hidinput_input_event;
-       hid->hidinput_open = hidinput_open;
-       hid->hidinput_close = hidinput_close;
+       hid->hid_open = usbhid_open;
+       hid->hid_close = usbhid_close;
 #ifdef CONFIG_USB_HIDDEV
        hid->hiddev_hid_event = hiddev_hid_event;
        hid->hiddev_report_event = hiddev_report_event;
@@ -1315,11 +1300,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
                return -ENODEV;
        }
 
-       /* This only gets called when we are a single-input (most of the
-        * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
-        * only useful in this case, and not for multi-input quirks. */
-       if ((hid->claimed & HID_CLAIMED_INPUT) &&
-                       !(hid->quirks & HID_QUIRK_MULTI_INPUT))
+       if ((hid->claimed & HID_CLAIMED_INPUT))
                hid_ff_init(hid);
 
        printk(KERN_INFO);
index 59ed65e7a6217f5e15e8756aaec816b6b9615eca..5d145058a5cb33cf40a14873b0e363f4b5e23b00 100644 (file)
@@ -58,6 +58,9 @@ static struct hid_ff_initializer inits[] = {
        { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
        { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
 #endif
+#ifdef CONFIG_PANTHERLORD_FF
+       { 0x810, 0x0001, hid_plff_init },
+#endif
 #ifdef CONFIG_THRUSTMASTER_FF
        { 0x44f, 0xb304, hid_tmff_init },
 #endif
diff --git a/drivers/usb/input/hid-plff.c b/drivers/usb/input/hid-plff.c
new file mode 100644 (file)
index 0000000..76d2e6e
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ *  Force feedback support for PantherLord USB/PS2 2in1 Adapter devices
+ *
+ *  Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+/* #define DEBUG */
+
+#define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg)
+
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+#include "usbhid.h"
+
+struct plff_device {
+       struct hid_report *report;
+};
+
+static int hid_plff_play(struct input_dev *dev, void *data,
+                        struct ff_effect *effect)
+{
+       struct hid_device *hid = dev->private;
+       struct plff_device *plff = data;
+       int left, right;
+
+       left = effect->u.rumble.strong_magnitude;
+       right = effect->u.rumble.weak_magnitude;
+       debug("called with 0x%04x 0x%04x", left, right);
+
+       left = left * 0x7f / 0xffff;
+       right = right * 0x7f / 0xffff;
+
+       plff->report->field[0]->value[2] = left;
+       plff->report->field[0]->value[3] = right;
+       debug("running with 0x%02x 0x%02x", left, right);
+       usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+
+       return 0;
+}
+
+int hid_plff_init(struct hid_device *hid)
+{
+       struct plff_device *plff;
+       struct hid_report *report;
+       struct hid_input *hidinput;
+       struct list_head *report_list =
+                       &hid->report_enum[HID_OUTPUT_REPORT].report_list;
+       struct list_head *report_ptr = report_list;
+       struct input_dev *dev;
+       int error;
+
+       /* The device contains 2 output reports (one for each
+          HID_QUIRK_MULTI_INPUT device), both containing 1 field, which
+          contains 4 ff00.0002 usages and 4 16bit absolute values.
+
+          The 2 input reports also contain a field which contains
+          8 ff00.0001 usages and 8 boolean values. Their meaning is
+          currently unknown. */
+
+       if (list_empty(report_list)) {
+               printk(KERN_ERR "hid-plff: no output reports found\n");
+               return -ENODEV;
+       }
+
+       list_for_each_entry(hidinput, &hid->inputs, list) {
+
+               report_ptr = report_ptr->next;
+
+               if (report_ptr == report_list) {
+                       printk(KERN_ERR "hid-plff: required output report is missing\n");
+                       return -ENODEV;
+               }
+
+               report = list_entry(report_ptr, struct hid_report, list);
+               if (report->maxfield < 1) {
+                       printk(KERN_ERR "hid-plff: no fields in the report\n");
+                       return -ENODEV;
+               }
+
+               if (report->field[0]->report_count < 4) {
+                       printk(KERN_ERR "hid-plff: not enough values in the field\n");
+                       return -ENODEV;
+               }
+
+               plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL);
+               if (!plff)
+                       return -ENOMEM;
+
+               dev = hidinput->input;
+
+               set_bit(FF_RUMBLE, dev->ffbit);
+
+               error = input_ff_create_memless(dev, plff, hid_plff_play);
+               if (error) {
+                       kfree(plff);
+                       return error;
+               }
+
+               plff->report = report;
+               plff->report->field[0]->value[0] = 0x00;
+               plff->report->field[0]->value[1] = 0x00;
+               plff->report->field[0]->value[2] = 0x00;
+               plff->report->field[0]->value[3] = 0x00;
+               usbhid_submit_report(hid, plff->report, USB_DIR_OUT);
+       }
+
+       printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 "
+              "2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n");
+
+       return 0;
+}
index d04d2f7448d9e4a872a0d548a54c47c411e6df2f..85e3850bf2c92a29e212bc7c6b576a5a04eb27c5 100644 (file)
@@ -1,6 +1,8 @@
 Version 1.47
 ------------
 Fix oops in list_del during mount caused by unaligned string.
+Seek to SEEK_END forces check for update of file size for non-cached
+files.
 
 Version 1.46
 ------------
index 10c90294cd1821c9fd273f688c50f6f85889d4cd..93ef09971d2fafb9f92ecd0eed6034c9661f1192 100644 (file)
@@ -511,7 +511,15 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin)
 {
        /* origin == SEEK_END => we must revalidate the cached file length */
        if (origin == SEEK_END) {
-               int retval = cifs_revalidate(file->f_path.dentry);
+               int retval;
+
+               /* some applications poll for the file length in this strange
+                  way so we must seek to end on non-oplocked files by
+                  setting the revalidate time to zero */
+               if(file->f_path.dentry->d_inode)                
+                       CIFS_I(file->f_path.dentry->d_inode)->time = 0;
+
+               retval = cifs_revalidate(file->f_path.dentry);
                if (retval < 0)
                        return (loff_t)retval;
        }
index 8a49b2e77d379ceaf9f0824089d79ee1392cb774..e9dcf5ee29a25bb42e765c57b5a916b84cd777c8 100644 (file)
@@ -1146,7 +1146,7 @@ static int cifs_writepages(struct address_space *mapping,
        pgoff_t end;
        pgoff_t index;
        int range_whole = 0;
-       struct kvec iov[32];
+       struct kvec * iov;
        int len;
        int n_iov = 0;
        pgoff_t next;
@@ -1171,15 +1171,21 @@ static int cifs_writepages(struct address_space *mapping,
        if((cifs_sb->tcon->ses) && (cifs_sb->tcon->ses->server))
                if(cifs_sb->tcon->ses->server->secMode &
                           (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-                       if(!experimEnabled)
+                       if(!experimEnabled) 
                                return generic_writepages(mapping, wbc);
 
+       iov = kmalloc(32 * sizeof(struct kvec), GFP_KERNEL);
+       if(iov == NULL)
+               return generic_writepages(mapping, wbc);
+
+
        /*
         * BB: Is this meaningful for a non-block-device file system?
         * If it is, we should test it again after we do I/O
         */
        if (wbc->nonblocking && bdi_write_congested(bdi)) {
                wbc->encountered_congestion = 1;
+               kfree(iov);
                return 0;
        }
 
@@ -1345,7 +1351,7 @@ retry:
                mapping->writeback_index = index;
 
        FreeXid(xid);
-
+       kfree(iov);
        return rc;
 }
 
index 99dfb5337e3169d8e38cf062a509326694b24a0d..782940be550f48b59077e944d5306df27c33036b 100644 (file)
@@ -156,9 +156,9 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
                tmp_inode->i_atime = cnvrtDosUnixTm(
                                le16_to_cpu(pfindData->LastAccessDate),
                                le16_to_cpu(pfindData->LastAccessTime));
-                tmp_inode->i_ctime = cnvrtDosUnixTm(
-                                le16_to_cpu(pfindData->LastWriteDate),
-                                le16_to_cpu(pfindData->LastWriteTime));
+               tmp_inode->i_ctime = cnvrtDosUnixTm(
+                               le16_to_cpu(pfindData->LastWriteDate),
+                               le16_to_cpu(pfindData->LastWriteTime));
                AdjustForTZ(cifs_sb->tcon, tmp_inode);
                attr = le16_to_cpu(pfindData->Attributes);
                allocation_size = le32_to_cpu(pfindData->AllocationSize);
index 7a1b2b961ec875b7f1a964d8f20f27b8fec58239..1b1daf63f06202cbb01974086aec490d04f0dcde 100644 (file)
@@ -196,7 +196,7 @@ dohash(char *out, char *in, char *key, int forw)
        char c[28];
        char d[28];
        char *cd;
-       char ki[16][48];
+       char (*ki)[48];
        char *pd1;
        char l[32], r[32];
        char *rl;
@@ -206,6 +206,12 @@ dohash(char *out, char *in, char *key, int forw)
        if(pk1 == NULL)
                return;
 
+       ki = kmalloc(16*48, GFP_KERNEL);
+       if(ki == NULL) {
+               kfree(pk1);
+               return;
+       }
+
        cd = pk1 + 56;
        pd1= cd  + 56;
        rl = pd1 + 64;
@@ -243,6 +249,7 @@ dohash(char *out, char *in, char *key, int forw)
                er = kmalloc(48+48+32+32+32, GFP_KERNEL);
                if(er == NULL) {
                        kfree(pk1);
+                       kfree(ki);
                        return;
                }
                erk = er+48;
@@ -290,6 +297,7 @@ dohash(char *out, char *in, char *key, int forw)
 
        permute(out, rl, perm6, 64);
        kfree(pk1);
+       kfree(ki);
 }
 
 static void
index e1216364d191566ba80b276796afb965fe8ebb61..d026b4f27757ebfb1d60346eabd074adb7d8d247 100644 (file)
@@ -306,8 +306,8 @@ int                  ocfs2_journal_dirty_data(handle_t *handle,
  * for the dinode, one for the new block. */
 #define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2)
 
-/* file update (nlink, etc) + dir entry block */
-#define OCFS2_LINK_CREDITS  (OCFS2_INODE_UPDATE_CREDITS + 1)
+/* file update (nlink, etc) + directory mtime/ctime + dir entry block */
+#define OCFS2_LINK_CREDITS  (2*OCFS2_INODE_UPDATE_CREDITS + 1)
 
 /* inode + dir inode (if we unlink a dir), + dir entry block + orphan
  * dir inode link */
index dad3a735df8bf2bdfb0905775f028259950fa35a..4d97f60f1ef57ce71194932ca8301741e0c6cfa2 100644 (file)
@@ -19,4 +19,6 @@ extern unsigned long MAX_DMA_ADDRESS;
 
 #define free_dma(x)
 
+void dma_mark_clean(void *addr, size_t size);
+
 #endif /* _ASM_IA64_DMA_H */
index 84aac0e0b583e7b795fc97fda0ed7ba59079c13c..40991c6ba6476530b79b5781217599b325b5e661 100644 (file)
@@ -19,7 +19,6 @@ enum esi_proc_type {
        ESI_PROC_REENTRANT      /* MP-safe and reentrant */
 };
 
-extern int ia64_esi_init (void);
 extern struct ia64_sal_retval esi_call_phys (void *, u64 *);
 extern int ia64_esi_call(efi_guid_t, struct ia64_sal_retval *,
                         enum esi_proc_type,
index c8df75901083ed67611b18c5153996d0cd27f29c..6dd476b652c6aba995e03d3208c50f21adcba594 100644 (file)
@@ -51,12 +51,13 @@ extern void efi_memmap_init(unsigned long *, unsigned long *);
 
 #define IGNORE_PFN0    1       /* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
 
+extern int register_active_ranges(u64 start, u64 end, void *arg);
+
 #ifdef CONFIG_VIRTUAL_MEM_MAP
 # define LARGE_GAP     0x40000000 /* Use virtual mem map if hole is > than this */
   extern unsigned long vmalloc_end;
   extern struct page *vmem_map;
   extern int find_largest_hole (u64 start, u64 end, void *arg);
-  extern int register_active_ranges (u64 start, u64 end, void *arg);
   extern int create_mem_map_page_table (u64 start, u64 end, void *arg);
   extern int vmemmap_find_next_valid_pfn(int, int);
 #else
index 393e04c42a2c127affc71db782b51214221e0934..560c287b12330c4e4f35860297a13f28c874a52b 100644 (file)
@@ -137,7 +137,8 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t * pmd_entry, pte_t * pte)
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
                                         unsigned long addr)
 {
-       return virt_to_page(pgtable_quicklist_alloc());
+       void *pg = pgtable_quicklist_alloc();
+       return pg ? virt_to_page(pg) : NULL;
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
diff --git a/include/asm-ia64/swiotlb.h b/include/asm-ia64/swiotlb.h
new file mode 100644 (file)
index 0000000..452c162
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _ASM_SWIOTLB_H
+#define _ASM_SWIOTLB_H 1
+
+#include <asm/machvec.h>
+
+#define SWIOTLB_ARCH_NEED_LATE_INIT
+#define SWIOTLB_ARCH_NEED_ALLOC
+
+#endif /* _ASM_SWIOTLB_H */
index 9b505b25544f0bd707063ba48e053a9afdebe030..91698599f91886f73bb591b6e0b12c84eaa1e2ac 100644 (file)
@@ -84,6 +84,7 @@ struct thread_info {
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
 #define TIF_SYSCALL_TRACE      3       /* syscall trace active */
 #define TIF_SYSCALL_AUDIT      4       /* syscall auditing active */
+#define TIF_SINGLESTEP         5       /* restore singlestep on return to user mode */
 #define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             17
 #define TIF_MCA_INIT           18      /* this task is processing MCA or INIT */
@@ -92,7 +93,8 @@ struct thread_info {
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
-#define _TIF_SYSCALL_TRACEAUDIT        (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
+#define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
+#define _TIF_SYSCALL_TRACEAUDIT        (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
index 53c5c0ee122c96291655807f05dc8a60d121773f..a9e1fa4cac4d46d652e534ce1bfaf54ddc1698bf 100644 (file)
 #define __NR_sync_file_range           1300
 #define __NR_tee                       1301
 #define __NR_vmsplice                  1302
+/* 1303 reserved for move_pages */
+#define __NR_getcpu                    1304
 
 #ifdef __KERNEL__
 
 
-#define NR_syscalls                    279 /* length of syscall table */
+#define NR_syscalls                    281 /* length of syscall table */
 
 #define __ARCH_WANT_SYS_RT_SIGACTION
 
index 8e321f53a38270570056b9d1bc5ae1fec70deaea..c7c945baf1ee6c4140468baa7f84d90e2391cf47 100644 (file)
@@ -243,6 +243,10 @@ extern struct boot_mem_map boot_mem_map;
 extern void add_memory_region(phys_t start, phys_t size, long type);
 
 extern void prom_init(void);
+extern void prom_free_prom_memory(void);
+
+extern void free_init_pages(const char *what,
+                           unsigned long begin, unsigned long end);
 
 /*
  * Initial kernel command line, usually setup by prom_init()
index c5af4b73fdd77ef3cb7fda33fa88ee8f31217264..6cf177caf6d52ce9b39ac122ad44a8356412982e 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef __ASM_DDB5XXX_DDB5477_H
 #define __ASM_DDB5XXX_DDB5477_H
 
+#include <irq.h>
 
 /*
  * This contains macros that are specific to DDB5477 or renamed from
@@ -251,14 +252,10 @@ extern void ll_vrc5477_irq_disable(int vrc5477_irq);
  */
 
 #define        NUM_CPU_IRQ             8
-#define        NUM_I8259_IRQ           16
 #define        NUM_VRC5477_IRQ         32
 
-#define        DDB_IRQ_BASE            0
-
-#define        I8259_IRQ_BASE          DDB_IRQ_BASE
-#define        VRC5477_IRQ_BASE        (I8259_IRQ_BASE + NUM_I8259_IRQ)
-#define        CPU_IRQ_BASE            (VRC5477_IRQ_BASE + NUM_VRC5477_IRQ)
+#define        CPU_IRQ_BASE            MIPS_CPU_IRQ_BASE
+#define        VRC5477_IRQ_BASE        (CPU_IRQ_BASE + NUM_CPU_IRQ)
 
 /*
  * vrc5477 irq defs
@@ -300,22 +297,22 @@ extern void ll_vrc5477_irq_disable(int vrc5477_irq);
 /*
  * i2859 irq assignment
  */
-#define I8259_IRQ_RESERVED_0   (0 + I8259_IRQ_BASE)
-#define I8259_IRQ_KEYBOARD     (1 + I8259_IRQ_BASE)    /* M1543 default */
-#define I8259_IRQ_CASCADE      (2 + I8259_IRQ_BASE)
-#define I8259_IRQ_UART_B       (3 + I8259_IRQ_BASE)    /* M1543 default, may conflict with RTC according to schematic diagram  */
-#define I8259_IRQ_UART_A       (4 + I8259_IRQ_BASE)    /* M1543 default */
-#define I8259_IRQ_PARALLEL     (5 + I8259_IRQ_BASE)    /* M1543 default */
-#define I8259_IRQ_RESERVED_6   (6 + I8259_IRQ_BASE)
-#define I8259_IRQ_RESERVED_7   (7 + I8259_IRQ_BASE)
-#define I8259_IRQ_RTC          (8 + I8259_IRQ_BASE)    /* who set this? */
-#define I8259_IRQ_USB          (9 + I8259_IRQ_BASE)    /* ddb_setup */
-#define I8259_IRQ_PMU          (10 + I8259_IRQ_BASE)   /* ddb_setup */
-#define I8259_IRQ_RESERVED_11  (11 + I8259_IRQ_BASE)
-#define I8259_IRQ_RESERVED_12  (12 + I8259_IRQ_BASE)   /* m1543_irq_setup */
-#define I8259_IRQ_RESERVED_13  (13 + I8259_IRQ_BASE)
-#define I8259_IRQ_HDC1         (14 + I8259_IRQ_BASE)   /* default and ddb_setup */
-#define I8259_IRQ_HDC2         (15 + I8259_IRQ_BASE)   /* default */
+#define I8259_IRQ_RESERVED_0   (0 + I8259A_IRQ_BASE)
+#define I8259_IRQ_KEYBOARD     (1 + I8259A_IRQ_BASE)   /* M1543 default */
+#define I8259_IRQ_CASCADE      (2 + I8259A_IRQ_BASE)
+#define I8259_IRQ_UART_B       (3 + I8259A_IRQ_BASE)   /* M1543 default, may conflict with RTC according to schematic diagram  */
+#define I8259_IRQ_UART_A       (4 + I8259A_IRQ_BASE)   /* M1543 default */
+#define I8259_IRQ_PARALLEL     (5 + I8259A_IRQ_BASE)   /* M1543 default */
+#define I8259_IRQ_RESERVED_6   (6 + I8259A_IRQ_BASE)
+#define I8259_IRQ_RESERVED_7   (7 + I8259A_IRQ_BASE)
+#define I8259_IRQ_RTC          (8 + I8259A_IRQ_BASE)   /* who set this? */
+#define I8259_IRQ_USB          (9 + I8259A_IRQ_BASE)   /* ddb_setup */
+#define I8259_IRQ_PMU          (10 + I8259A_IRQ_BASE)  /* ddb_setup */
+#define I8259_IRQ_RESERVED_11  (11 + I8259A_IRQ_BASE)
+#define I8259_IRQ_RESERVED_12  (12 + I8259A_IRQ_BASE)  /* m1543_irq_setup */
+#define I8259_IRQ_RESERVED_13  (13 + I8259A_IRQ_BASE)
+#define I8259_IRQ_HDC1         (14 + I8259A_IRQ_BASE)  /* default and ddb_setup */
+#define I8259_IRQ_HDC2         (15 + I8259A_IRQ_BASE)  /* default */
 
 
 /*
index 273e4d65bfe6ce7be4ed14328328688ba2aa9955..e10d341067c82fca2ee3d00930121469694ddd95 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef __ASM_DEC_INTERRUPTS_H
 #define __ASM_DEC_INTERRUPTS_H
 
+#include <irq.h>
 #include <asm/mipsregs.h>
 
 
@@ -87,7 +88,7 @@
 #define DEC_CPU_INR_SW1                1       /* software #1 */
 #define DEC_CPU_INR_SW0                0       /* software #0 */
 
-#define DEC_CPU_IRQ_BASE       0       /* first IRQ assigned to CPU */
+#define DEC_CPU_IRQ_BASE       MIPS_CPU_IRQ_BASE       /* first IRQ assigned to CPU */
 
 #define DEC_CPU_IRQ_NR(n)      ((n) + DEC_CPU_IRQ_BASE)
 #define DEC_CPU_IRQ_MASK(n)    (1 << ((n) + CAUSEB_IP))
index 23f789c80845c5d8814343bfa910d82e701a14b3..e06ef0776d48950f3b0ea556219ea2c2c84a3fce 100644 (file)
@@ -91,6 +91,7 @@
 #else
 #define MAX_DMA_ADDRESS                (PAGE_OFFSET + 0x01000000)
 #endif
+#define MAX_DMA_PFN            PFN_DOWN(virt_to_phys((void *)MAX_DMA_ADDRESS))
 
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE   0x00    /* 8 bit slave DMA, channels 0..3 */
index 4fb8df71caa9f0aa96ea2d8c1e97c1308969ecbe..6a1af0af51e3b221e57ec02761d865914677afe1 100644 (file)
@@ -24,6 +24,8 @@
 #ifndef __ASM_EMMA2RH_EMMA2RH_H
 #define __ASM_EMMA2RH_EMMA2RH_H
 
+#include <irq.h>
+
 /*
  * EMMA2RH registers
  */
 #define NUM_EMMA2RH_IRQ                96
 
 #define CPU_EMMA2RH_CASCADE    2
-#define EMMA2RH_IRQ_BASE       0
+#define CPU_IRQ_BASE           MIPS_CPU_IRQ_BASE
+#define EMMA2RH_IRQ_BASE       (CPU_IRQ_BASE + NUM_CPU_IRQ)
 
 /*
  * emma2rh irq defs
index 8fa766795078f978a5fbba04e15a6d5e833dc0a8..973b0628490db4dfa36af9d6d13bc9217785e2da 100644 (file)
@@ -33,7 +33,6 @@
 
 #define EMMA2RH_SW_IRQ_BASE    (EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ)
 #define EMMA2RH_GPIO_IRQ_BASE  (EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW)
-#define CPU_IRQ_BASE           (EMMA2RH_GPIO_IRQ_BASE + NUM_EMMA2RH_IRQ_GPIO)
 
 #define EMMA2RH_SW_IRQ_INT0    (0+EMMA2RH_SW_IRQ_BASE)
 #define EMMA2RH_SW_IRQ_INT1    (1+EMMA2RH_SW_IRQ_BASE)
index 4df8d8b118c05fef180002091c18e6b56fcf187f..e88a01607feab6ae9b9fbfa0d109dae1dae04d9d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 
 #include <asm/io.h>
+#include <irq.h>
 
 /* i8259A PIC registers */
 #define PIC_MASTER_CMD         0x20
@@ -42,8 +43,6 @@ extern void disable_8259A_irq(unsigned int irq);
 
 extern void init_i8259_irqs(void);
 
-#define I8259A_IRQ_BASE        0
-
 /*
  * Do the traditional i8259 interrupt polling thing.  This is for the few
  * cases where no better interrupt acknowledge method is available and we
index d77b657c09c794e03ae04c89e7e2018f50809168..67f081078904b0103d8d5bb3e15ad7f43a1f58b0 100644 (file)
@@ -115,7 +115,7 @@ static inline void set_io_port_base(unsigned long base)
  */
 static inline unsigned long virt_to_phys(volatile const void *address)
 {
-       return (unsigned long)address - PAGE_OFFSET;
+       return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;
 }
 
 /*
@@ -132,7 +132,7 @@ static inline unsigned long virt_to_phys(volatile const void *address)
  */
 static inline void * phys_to_virt(unsigned long address)
 {
-       return (void *)(address + PAGE_OFFSET);
+       return (void *)(address + PAGE_OFFSET - PHYS_OFFSET);
 }
 
 /*
index 386da82e57747e4cc08b9351fe71f23e7be6a412..91803ba30ff2abd2ac5d4c19b39b1f4590e5af8d 100644 (file)
@@ -18,7 +18,7 @@
 #ifdef CONFIG_I8259
 static inline int irq_canonicalize(int irq)
 {
-       return ((irq == 2) ? 9 : irq);
+       return ((irq == I8259A_IRQ_BASE + 2) ? I8259A_IRQ_BASE + 9 : irq);
 }
 #else
 #define irq_canonicalize(irq) (irq)    /* Sane hardware, sane code ... */
index ed3d1e3d09ec8dbd14e97462e0d821f35f4a4fdd..ef6a07cddb231d0b142fd94eeab0eb34d311a9e4 100644 (file)
@@ -13,8 +13,8 @@
 #ifndef _ASM_IRQ_CPU_H
 #define _ASM_IRQ_CPU_H
 
-extern void mips_cpu_irq_init(int irq_base);
-extern void rm7k_cpu_irq_init(int irq_base);
-extern void rm9k_cpu_irq_init(int irq_base);
+extern void mips_cpu_irq_init(void);
+extern void rm7k_cpu_irq_init(void);
+extern void rm9k_cpu_irq_init(void);
 
 #endif /* _ASM_IRQ_CPU_H */
index 582acd8adb81fd17d77cef2defbe8a606ec9312b..58fca8a5a9a69361e4813abad7db7e841a2a878b 100644 (file)
@@ -39,6 +39,7 @@
 #ifndef _LANGUAGE_ASSEMBLY
 
 #include <linux/delay.h>
+#include <linux/types.h>
 #include <asm/io.h>
 
 /* cpu pipeline flush */
index 00b0fc68d5cb19bb9767ecf0d7960a1ca464d085..24a8d51a55a35ec4b5725695cb1b93718c65326b 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef __ASM_COBALT_H
 #define __ASM_COBALT_H
 
+#include <irq.h>
+
 /*
  * i8259 legacy interrupts used on Cobalt:
  *
@@ -25,7 +27,7 @@
 /*
  * CPU IRQs  are 16 ... 23
  */
-#define COBALT_CPU_IRQ         16
+#define COBALT_CPU_IRQ         MIPS_CPU_IRQ_BASE
 
 #define COBALT_GALILEO_IRQ     (COBALT_CPU_IRQ + 2)
 #define COBALT_SCC_IRQ          (COBALT_CPU_IRQ + 3)   /* pre-production has 85C30 */
index bce64244b800dff2008523890a275e4ea2c3e2eb..5439eb85646101b36c80c2727eb0a17d9f822be9 100644 (file)
@@ -10,4 +10,6 @@
 
 #define NR_IRQS        256
 
+#include_next <irq.h>
+
 #endif /* __ASM_MACH_EMMA2RH_IRQ_H */
index 500e10ff24dea329e4321af0899e0348098466bc..70d9a25132c5265846febc873c0a90626e7c0f9f 100644 (file)
@@ -8,6 +8,38 @@
 #ifndef __ASM_MACH_GENERIC_IRQ_H
 #define __ASM_MACH_GENERIC_IRQ_H
 
+#ifndef NR_IRQS
 #define NR_IRQS        128
+#endif
+
+#ifdef CONFIG_I8259
+#ifndef I8259A_IRQ_BASE
+#define I8259A_IRQ_BASE        0
+#endif
+#endif
+
+#ifdef CONFIG_IRQ_CPU
+
+#ifndef MIPS_CPU_IRQ_BASE
+#ifdef CONFIG_I8259
+#define MIPS_CPU_IRQ_BASE 16
+#else
+#define MIPS_CPU_IRQ_BASE 0
+#endif /* CONFIG_I8259 */
+#endif
+
+#ifdef CONFIG_IRQ_CPU_RM7K
+#ifndef RM7K_CPU_IRQ_BASE
+#define RM7K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+8)
+#endif
+#endif
+
+#ifdef CONFIG_IRQ_CPU_RM9K
+#ifndef RM9K_CPU_IRQ_BASE
+#define RM9K_CPU_IRQ_BASE (MIPS_CPU_IRQ_BASE+12)
+#endif
+#endif
+
+#endif /* CONFIG_IRQ_CPU */
 
 #endif /* __ASM_MACH_GENERIC_IRQ_H */
index e994b0c012279a316693e403b4f94d80ea522c4d..9b9da26683c22448d3b0a1b4a69f6a81ba585d3d 100644 (file)
@@ -4,4 +4,6 @@
 
 #define NR_IRQS        256
 
+#include_next <irq.h>
+
 #endif /* __ASM_MACH_MIPS_IRQ_H */
diff --git a/include/asm-mips/mach-vr41xx/irq.h b/include/asm-mips/mach-vr41xx/irq.h
new file mode 100644 (file)
index 0000000..8488122
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __ASM_MACH_VR41XX_IRQ_H
+#define __ASM_MACH_VR41XX_IRQ_H
+
+#include <asm/vr41xx/irq.h> /* for MIPS_CPU_IRQ_BASE */
+#ifdef CONFIG_NEC_CMBVR4133
+#include <asm/vr41xx/cmbvr4133.h> /* for I8259A_IRQ_BASE */
+#endif
+
+#include_next <irq.h>
+
+#endif /* __ASM_MACH_VR41XX_IRQ_H */
index b15e4ea0b0911bdffa62b3c122663d9f8b8a5134..76add42e486e292b816e487ab8cbbe565607bd14 100644 (file)
 #ifndef _MIPS_ATLASINT_H
 #define _MIPS_ATLASINT_H
 
+#include <irq.h>
+
 /*
  * Interrupts 0..7 are used for Atlas CPU interrupts (nonEIC mode)
  */
-#define MIPSCPU_INT_BASE       0
+#define MIPSCPU_INT_BASE       MIPS_CPU_IRQ_BASE
 
 /* CPU interrupt offsets */
 #define MIPSCPU_INT_SW0                0
index da6cc2fbbc780990e1685973b064697aa7bb19ea..9180d6466113f4fb5b6a86de84b19eaed122173b 100644 (file)
@@ -25,6 +25,8 @@
 #ifndef _MIPS_MALTAINT_H
 #define _MIPS_MALTAINT_H
 
+#include <irq.h>
+
 /*
  * Interrupts 0..15 are used for Malta ISA compatible interrupts
  */
@@ -33,7 +35,7 @@
 /*
  * Interrupts 16..23 are used for Malta CPU interrupts (nonEIC mode)
  */
-#define MIPSCPU_INT_BASE       16
+#define MIPSCPU_INT_BASE       MIPS_CPU_IRQ_BASE
 
 /* CPU interrupt offsets */
 #define MIPSCPU_INT_SW0                0
index 4168c7fcd43e7e46fdbb33e1127bfa38a6cc4419..7bf6f5f6ab9c0845db161e521d21cef8d9ad642b 100644 (file)
@@ -33,7 +33,6 @@ extern void prom_printf(char *fmt, ...);
 extern void prom_init_cmdline(void);
 extern void prom_meminit(void);
 extern void prom_fixup_mem_map(unsigned long start_mem, unsigned long end_mem);
-extern unsigned long prom_free_prom_memory (void);
 extern void mips_display_message(const char *str);
 extern void mips_display_word(unsigned int num);
 extern int get_ethernet_addr(char *ethernet_addr);
index 365c2a3c64f5edb1c39017ed2185afac369c96cc..4f6a3933699d12ed613551477466af19ac9b6862 100644 (file)
 #ifndef _MIPS_SEADINT_H
 #define _MIPS_SEADINT_H
 
+#include <irq.h>
+
 /*
  * Interrupts 0..7 are used for SEAD CPU interrupts
  */
-#define MIPSCPU_INT_BASE       0
+#define MIPSCPU_INT_BASE       MIPS_CPU_IRQ_BASE
 
 #define MIPSCPU_INT_UART0      2
 #define MIPSCPU_INT_UART1      3
index 4952e0b3bf1129bf9515e42bdc5160672c2b4b5b..54f2fe621d6913498899fa6bc63a09845813cdfa 100644 (file)
 #ifndef _MIPS_SIMINT_H
 #define _MIPS_SIMINT_H
 
+#include <irq.h>
 
 #define SIM_INT_BASE           0
 #define MIPSCPU_INT_MB0                2
-#define MIPSCPU_INT_BASE       16
+#define MIPSCPU_INT_BASE       MIPS_CPU_IRQ_BASE
 #define MIPS_CPU_TIMER_IRQ     7
 
 
index 3e9468f424f43a7ed51b513b4416c23f44ee21ca..294bca12cd3fd443183aeb85cdb505f7d1822484 100644 (file)
 
 #ifndef __ASSEMBLY__
 
-extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
-
 static inline unsigned int dvpe(void)
 {
        int res = 0;
index 2f9e1a9ec51f2e8c85ee24f79eecffeeff69143c..d3fbd83ff545e49e2a0a5ca0f00dda4eedaf8be7 100644 (file)
 
 #ifndef __ASSEMBLY__
 
+/*
+ * This gives the physical RAM offset.
+ */
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET            0UL
+#endif
+
+/*
+ * It's normally defined only for FLATMEM config but it's
+ * used in our early mem init code for all memory models.
+ * So always define it.
+ */
+#define ARCH_PFN_OFFSET                PFN_UP(PHYS_OFFSET)
+
 #include <linux/pfn.h>
 #include <asm/io.h>
 
@@ -132,20 +146,23 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)       (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
 
+/*
+ * __pa()/__va() should be used only during mem init.
+ */
 #if defined(CONFIG_64BIT) && !defined(CONFIG_BUILD_ELF64)
 #define __pa_page_offset(x)    ((unsigned long)(x) < CKSEG0 ? PAGE_OFFSET : CKSEG0)
 #else
 #define __pa_page_offset(x)    PAGE_OFFSET
 #endif
-#define __pa(x)                        ((unsigned long)(x) - __pa_page_offset(x))
-#define __pa_symbol(x)         __pa(RELOC_HIDE((unsigned long)(x),0))
-#define __va(x)                        ((void *)((unsigned long)(x) + PAGE_OFFSET))
+#define __pa(x)                ((unsigned long)(x) - __pa_page_offset(x) + PHYS_OFFSET)
+#define __va(x)                ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
+#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x),0))
 
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
 
 #ifdef CONFIG_FLATMEM
 
-#define pfn_valid(pfn)         ((pfn) < max_mapnr)
+#define pfn_valid(pfn)         ((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr)
 
 #elif defined(CONFIG_SPARSEMEM)
 
index 76cd51c6be397979beb615f70914b413f9ccfef1..59162f74a7982b98801fe903aceafe0fe08354a5 100644 (file)
@@ -6,9 +6,10 @@
 #ifndef __ASM_RTLX_H
 #define __ASM_RTLX_H_
 
+#include <irq.h>
+
 #define LX_NODE_BASE 10
 
-#define MIPSCPU_INT_BASE       16
 #define MIPS_CPU_RTLX_IRQ 0
 
 #define RTLX_VERSION 2
index f7016278b266f9ecb7b87a90761ad4bb431f602a..b7e37262c2464576fc2b88cac1f7e522fa3046e7 100644 (file)
@@ -3,6 +3,4 @@
 
 #include <asm-generic/sections.h>
 
-extern char _fdata;
-
 #endif /* _ASM_SECTIONS_H */
index bbfc05c3cab93c26137930b7e5b1fece233f0036..6592f3bd19994eaa3eff6a04773e08b8ceae1374 100644 (file)
  * HAL2 driver). This will prevent many complications, trust me ;-)
  */
 
+#include <irq.h>
 #include <asm/sgi/ioc.h>
 
 #define SGINT_EISA     0       /* 16 EISA irq levels (Indigo2) */
-#define SGINT_CPU      16      /* MIPS CPU define 8 interrupt sources */
-#define SGINT_LOCAL0   24      /* 8 local0 irq levels */
-#define SGINT_LOCAL1   32      /* 8 local1 irq levels */
-#define SGINT_LOCAL2   40      /* 8 local2 vectored irq levels */
-#define SGINT_LOCAL3   48      /* 8 local3 vectored irq levels */
-#define SGINT_END      56      /* End of 'spaces' */
+#define SGINT_CPU      MIPS_CPU_IRQ_BASE       /* MIPS CPU define 8 interrupt sources */
+#define SGINT_LOCAL0   (SGINT_CPU+8)   /* 8 local0 irq levels */
+#define SGINT_LOCAL1   (SGINT_CPU+16)  /* 8 local1 irq levels */
+#define SGINT_LOCAL2   (SGINT_CPU+24)  /* 8 local2 vectored irq levels */
+#define SGINT_LOCAL3   (SGINT_CPU+32)  /* 8 local3 vectored irq levels */
+#define SGINT_END      (SGINT_CPU+40)  /* End of 'spaces' */
 
 /*
  * Individual interrupt definitions for the Indy and Indigo2
index f22c3e2f993aa29424765dc030fff9ebe9ca2a28..55f3419f65465892f35630c3a32b730866ed77e1 100644 (file)
@@ -44,9 +44,6 @@ struct smtc_ipi_q {
        int depth;
 };
 
-extern struct smtc_ipi_q IPIQ[NR_CPUS];
-extern struct smtc_ipi_q freeIPIq;
-
 static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
 {
        long flags;
index 1cdd4eeb2f735e5b8f27bd0e476348ce9056737f..c12ebc53ef317f4ac6bcd146736b65bde0f4243f 100644 (file)
@@ -488,7 +488,8 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 })
 
 /*
- * __copy_from_user: - Copy a block of data from user space, with less checking. * @to:   Destination address, in kernel space.
+ * __copy_from_user: - Copy a block of data from user space, with less checking.
+ * @to:   Destination address, in kernel space.
  * @from: Source address, in user space.
  * @n:    Number of bytes to copy.
  *
index 9490ade58b4689f47868d3aa777d84101f9fbd68..42300037d5938648bc6523dbb4708df654147c18 100644 (file)
@@ -35,8 +35,8 @@
 #define CMBVR41XX_INTD_IRQ             GIU_IRQ(CMBVR41XX_INTD_PIN)
 #define CMBVR41XX_INTE_IRQ             GIU_IRQ(CMBVR41XX_INTE_PIN)
 
-#define I8259_IRQ_BASE                 72
-#define I8259_IRQ(x)                   (I8259_IRQ_BASE + (x))
+#define I8259A_IRQ_BASE                        72
+#define I8259_IRQ(x)                   (I8259A_IRQ_BASE + (x))
 #define TIMER_IRQ                      I8259_IRQ(0)
 #define KEYBOARD_IRQ                   I8259_IRQ(1)
 #define I8259_SLAVE_IRQ                        I8259_IRQ(2)
@@ -52,6 +52,5 @@
 #define AUX_IRQ                                I8259_IRQ(12)
 #define IDE_PRIMARY_IRQ                        I8259_IRQ(14)
 #define IDE_SECONDARY_IRQ              I8259_IRQ(15)
-#define I8259_IRQ_LAST                 IDE_SECONDARY_IRQ
 
 #endif /* __NEC_CMBVR4133_H */
index 356a0b1835390bd0e2cc56ad35626e44d58e49ac..296f4f1a20e1a2f8a79c89210091316348141f46 100644 (file)
@@ -6,6 +6,34 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 
+#define PSW32_MASK_PER         0x40000000UL
+#define PSW32_MASK_DAT         0x04000000UL
+#define PSW32_MASK_IO          0x02000000UL
+#define PSW32_MASK_EXT         0x01000000UL
+#define PSW32_MASK_KEY         0x00F00000UL
+#define PSW32_MASK_MCHECK      0x00040000UL
+#define PSW32_MASK_WAIT                0x00020000UL
+#define PSW32_MASK_PSTATE      0x00010000UL
+#define PSW32_MASK_ASC         0x0000C000UL
+#define PSW32_MASK_CC          0x00003000UL
+#define PSW32_MASK_PM          0x00000f00UL
+
+#define PSW32_ADDR_AMODE31     0x80000000UL
+#define PSW32_ADDR_INSN                0x7FFFFFFFUL
+
+#define PSW32_BASE_BITS                0x00080000UL
+
+#define PSW32_ASC_PRIMARY      0x00000000UL
+#define PSW32_ASC_ACCREG       0x00004000UL
+#define PSW32_ASC_SECONDARY    0x00008000UL
+#define PSW32_ASC_HOME         0x0000C000UL
+
+#define PSW32_MASK_MERGE(CURRENT,NEW) \
+       (((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
+        ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))
+
+extern long psw32_user_bits;
+
 #define COMPAT_USER_HZ 100
 
 typedef u32            compat_size_t;
diff --git a/include/asm-s390/etr.h b/include/asm-s390/etr.h
new file mode 100644 (file)
index 0000000..b498f19
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ *  include/asm-s390/etr.h
+ *
+ *  Copyright IBM Corp. 2006
+ *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+#ifndef __S390_ETR_H
+#define __S390_ETR_H
+
+/* ETR attachment control register */
+struct etr_eacr {
+       unsigned int e0         : 1;    /* port 0 stepping control */
+       unsigned int e1         : 1;    /* port 1 stepping control */
+       unsigned int _pad0      : 5;    /* must be 00100 */
+       unsigned int dp         : 1;    /* data port control */
+       unsigned int p0         : 1;    /* port 0 change recognition control */
+       unsigned int p1         : 1;    /* port 1 change recognition control */
+       unsigned int _pad1      : 3;    /* must be 000 */
+       unsigned int ea         : 1;    /* ETR alert control */
+       unsigned int es         : 1;    /* ETR sync check control */
+       unsigned int sl         : 1;    /* switch to local control */
+} __attribute__ ((packed));
+
+/* Port state returned by steai */
+enum etr_psc {
+       etr_psc_operational = 0,
+       etr_psc_semi_operational = 1,
+       etr_psc_protocol_error =  4,
+       etr_psc_no_symbols = 8,
+       etr_psc_no_signal = 12,
+       etr_psc_pps_mode = 13
+};
+
+/* Logical port state returned by stetr */
+enum etr_lpsc {
+       etr_lpsc_operational_step = 0,
+       etr_lpsc_operational_alt = 1,
+       etr_lpsc_semi_operational = 2,
+       etr_lpsc_protocol_error =  4,
+       etr_lpsc_no_symbol_sync = 8,
+       etr_lpsc_no_signal = 12,
+       etr_lpsc_pps_mode = 13
+};
+
+/* ETR status words */
+struct etr_esw {
+       struct etr_eacr eacr;           /* attachment control register */
+       unsigned int y          : 1;    /* stepping mode */
+       unsigned int _pad0      : 5;    /* must be 00000 */
+       unsigned int p          : 1;    /* stepping port number */
+       unsigned int q          : 1;    /* data port number */
+       unsigned int psc0       : 4;    /* port 0 state code */
+       unsigned int psc1       : 4;    /* port 1 state code */
+} __attribute__ ((packed));
+
+/* Second level data register status word */
+struct etr_slsw {
+       unsigned int vv1        : 1;    /* copy of validity bit data frame 1 */
+       unsigned int vv2        : 1;    /* copy of validity bit data frame 2 */
+       unsigned int vv3        : 1;    /* copy of validity bit data frame 3 */
+       unsigned int vv4        : 1;    /* copy of validity bit data frame 4 */
+       unsigned int _pad0      : 19;   /* must by all zeroes */
+       unsigned int n          : 1;    /* EAF port number */
+       unsigned int v1         : 1;    /* validity bit ETR data frame 1 */
+       unsigned int v2         : 1;    /* validity bit ETR data frame 2 */
+       unsigned int v3         : 1;    /* validity bit ETR data frame 3 */
+       unsigned int v4         : 1;    /* validity bit ETR data frame 4 */
+       unsigned int _pad1      : 4;    /* must be 0000 */
+} __attribute__ ((packed));
+
+/* ETR data frames */
+struct etr_edf1 {
+       unsigned int u          : 1;    /* untuned bit */
+       unsigned int _pad0      : 1;    /* must be 0 */
+       unsigned int r          : 1;    /* service request bit */
+       unsigned int _pad1      : 4;    /* must be 0000 */
+       unsigned int a          : 1;    /* time adjustment bit */
+       unsigned int net_id     : 8;    /* ETR network id */
+       unsigned int etr_id     : 8;    /* id of ETR which sends data frames */
+       unsigned int etr_pn     : 8;    /* port number of ETR output port */
+} __attribute__ ((packed));
+
+struct etr_edf2 {
+       unsigned int etv        : 32;   /* Upper 32 bits of TOD. */
+} __attribute__ ((packed));
+
+struct etr_edf3 {
+       unsigned int rc         : 8;    /* failure reason code */
+       unsigned int _pad0      : 3;    /* must be 000 */
+       unsigned int c          : 1;    /* ETR coupled bit */
+       unsigned int tc         : 4;    /* ETR type code */
+       unsigned int blto       : 8;    /* biased local time offset */
+                                       /* (blto - 128) * 15 = minutes */
+       unsigned int buo        : 8;    /* biased utc offset */
+                                       /* (buo - 128) = leap seconds */
+} __attribute__ ((packed));
+
+struct etr_edf4 {
+       unsigned int ed         : 8;    /* ETS device dependent data */
+       unsigned int _pad0      : 1;    /* must be 0 */
+       unsigned int buc        : 5;    /* biased ut1 correction */
+                                       /* (buc - 16) * 0.1 seconds */
+       unsigned int em         : 6;    /* ETS error magnitude */
+       unsigned int dc         : 6;    /* ETS drift code */
+       unsigned int sc         : 6;    /* ETS steering code */
+} __attribute__ ((packed));
+
+/*
+ * ETR attachment information block, two formats
+ * format 1 has 4 reserved words with a size of 64 bytes
+ * format 2 has 16 reserved words with a size of 96 bytes
+ */
+struct etr_aib {
+       struct etr_esw esw;
+       struct etr_slsw slsw;
+       unsigned long long tsp;
+       struct etr_edf1 edf1;
+       struct etr_edf2 edf2;
+       struct etr_edf3 edf3;
+       struct etr_edf4 edf4;
+       unsigned int reserved[16];
+} __attribute__ ((packed,aligned(8)));
+
+/* ETR interruption parameter */
+struct etr_interruption_parameter {
+       unsigned int _pad0      : 8;
+       unsigned int pc0        : 1;    /* port 0 state change */
+       unsigned int pc1        : 1;    /* port 1 state change */
+       unsigned int _pad1      : 3;
+       unsigned int eai        : 1;    /* ETR alert indication */
+       unsigned int _pad2      : 18;
+} __attribute__ ((packed));
+
+/* Query TOD offset result */
+struct etr_ptff_qto {
+       unsigned long long physical_clock;
+       unsigned long long tod_offset;
+       unsigned long long logical_tod_offset;
+       unsigned long long tod_epoch_difference;
+} __attribute__ ((packed));
+
+/* Inline assembly helper functions */
+static inline int etr_setr(struct etr_eacr *ctrl)
+{
+       int rc = -ENOSYS;
+
+       asm volatile(
+               "       .insn   s,0xb2160000,0(%2)\n"
+               "0:     la      %0,0\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (rc) : "m" (*ctrl), "a" (ctrl));
+       return rc;
+}
+
+/* Stores a format 1 aib with 64 bytes */
+static inline int etr_stetr(struct etr_aib *aib)
+{
+       int rc = -ENOSYS;
+
+       asm volatile(
+               "       .insn   s,0xb2170000,0(%2)\n"
+               "0:     la      %0,0\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (rc) : "m" (*aib), "a" (aib));
+       return rc;
+}
+
+/* Stores a format 2 aib with 96 bytes for specified port */
+static inline int etr_steai(struct etr_aib *aib, unsigned int func)
+{
+       register unsigned int reg0 asm("0") = func;
+       int rc = -ENOSYS;
+
+       asm volatile(
+               "       .insn   s,0xb2b30000,0(%2)\n"
+               "0:     la      %0,0\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (rc) : "m" (*aib), "a" (aib), "d" (reg0));
+       return rc;
+}
+
+/* Function codes for the steai instruction. */
+#define ETR_STEAI_STEPPING_PORT                0x10
+#define ETR_STEAI_ALTERNATE_PORT       0x11
+#define ETR_STEAI_PORT_0               0x12
+#define ETR_STEAI_PORT_1               0x13
+
+static inline int etr_ptff(void *ptff_block, unsigned int func)
+{
+       register unsigned int reg0 asm("0") = func;
+       register unsigned long reg1 asm("1") = (unsigned long) ptff_block;
+       int rc = -ENOSYS;
+
+       asm volatile(
+               "       .word   0x0104\n"
+               "       ipm     %0\n"
+               "       srl     %0,28\n"
+               : "=d" (rc), "=m" (ptff_block)
+               : "d" (reg0), "d" (reg1), "m" (ptff_block) : "cc");
+       return rc;
+}
+
+/* Function codes for the ptff instruction. */
+#define ETR_PTFF_QAF   0x00    /* query available functions */
+#define ETR_PTFF_QTO   0x01    /* query tod offset */
+#define ETR_PTFF_QSI   0x02    /* query steering information */
+#define ETR_PTFF_ATO   0x40    /* adjust tod offset */
+#define ETR_PTFF_STO   0x41    /* set tod offset */
+#define ETR_PTFF_SFS   0x42    /* set fine steering rate */
+#define ETR_PTFF_SGS   0x43    /* set gross steering rate */
+
+/* Functions needed by the machine check handler */
+extern void etr_switch_to_local(void);
+extern void etr_sync_check(void);
+
+#endif /* __S390_ETR_H */
index c2f6a8782d31b5a901b3e5e8d7dc7dc9ecbad3aa..31beb18cb3d1ecab270f4f4cb66e1211cbca0080 100644 (file)
@@ -32,6 +32,6 @@ typedef struct {
 
 #define HARDIRQ_BITS   8
 
-extern void account_ticks(void);
+extern void account_ticks(u64 time);
 
 #endif /* __ASM_HARDIRQ_H */
index efb7de9c1c6bc815ba5e5f04d32967ec6b2cad2b..a4c2d550dad4268e97836bda9ea6d6f48416cf8a 100644 (file)
@@ -28,11 +28,7 @@ static inline unsigned long virt_to_phys(volatile void * address)
 {
        unsigned long real_address;
        asm volatile(
-#ifndef __s390x__
                 "      lra     %0,0(%1)\n"
-#else /* __s390x__ */
-                "      lrag    %0,0(%1)\n"
-#endif /* __s390x__ */
                 "      jz      0f\n"
                 "      la      %0,0\n"
                  "0:"
index 40cc68025e016e72b85ab128f535d728f0f521fe..1b50f89819a493b1db265a93e88edac8ef3ae0b7 100644 (file)
@@ -26,7 +26,6 @@ extern int register_page_fault_notifier(struct notifier_block *);
 extern int unregister_page_fault_notifier(struct notifier_block *);
 extern struct atomic_notifier_head s390die_chain;
 
-
 enum die_val {
        DIE_OOPS = 1,
        DIE_BPT,
@@ -56,4 +55,6 @@ static inline int notify_die(enum die_val val, const char *str,
        return atomic_notifier_call_chain(&s390die_chain, val, &args);
 }
 
+extern void die(const char *, struct pt_regs *, long);
+
 #endif
index 74f7389bd3ee05004620f3370fe23b8458dc78d8..4a31d0a7ee83ef78a1fb207e2b86733d809603fa 100644 (file)
@@ -220,7 +220,8 @@ struct _lowcore
        __u32        kernel_asce;              /* 0xc4c */
        __u32        user_asce;                /* 0xc50 */
        __u32        panic_stack;              /* 0xc54 */
-       __u8         pad10[0xc60-0xc58];       /* 0xc58 */
+       __u32        user_exec_asce;           /* 0xc58 */
+       __u8         pad10[0xc60-0xc5c];       /* 0xc5c */
        /* entry.S sensitive area start */
        struct       cpuinfo_S390 cpu_data;    /* 0xc60 */
        __u32        ipl_device;               /* 0xc7c */
@@ -310,7 +311,8 @@ struct _lowcore
        __u64        kernel_asce;              /* 0xd58 */
        __u64        user_asce;                /* 0xd60 */
        __u64        panic_stack;              /* 0xd68 */
-       __u8         pad10[0xd80-0xd70];       /* 0xd70 */
+       __u64        user_exec_asce;           /* 0xd70 */
+       __u8         pad10[0xd80-0xd78];       /* 0xd78 */
        /* entry.S sensitive area start */
        struct       cpuinfo_S390 cpu_data;    /* 0xd80 */
        __u32        ipl_device;               /* 0xdb8 */
index bcf24a8738740e4b663a9d22e486b82978e9f11b..1d21da220d49b8779ad3e916d67c54dfc1f73547 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef __S390_MMU_CONTEXT_H
 #define __S390_MMU_CONTEXT_H
 
+#include <asm/pgalloc.h>
 /*
  * get a new mmu context.. S390 don't know about contexts.
  */
 
 #define destroy_context(mm)             do { } while (0)
 
+#ifndef __s390x__
+#define LCTL_OPCODE "lctl"
+#define PGTABLE_BITS (_SEGMENT_TABLE|USER_STD_MASK)
+#else
+#define LCTL_OPCODE "lctlg"
+#define PGTABLE_BITS (_REGION_TABLE|USER_STD_MASK)
+#endif
+
 static inline void enter_lazy_tlb(struct mm_struct *mm,
                                   struct task_struct *tsk)
 {
 }
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
-                             struct task_struct *tsk)
+                            struct task_struct *tsk)
 {
-        if (prev != next) {
-#ifndef __s390x__
-               S390_lowcore.user_asce = (__pa(next->pgd)&PAGE_MASK) |
-                      (_SEGMENT_TABLE|USER_STD_MASK);
-                /* Load home space page table origin. */
-                asm volatile("lctl  13,13,%0"
-                            : : "m" (S390_lowcore.user_asce) );
-#else /* __s390x__ */
-                S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) |
-                       (_REGION_TABLE|USER_STD_MASK);
-               /* Load home space page table origin. */
-               asm volatile("lctlg  13,13,%0"
-                            : : "m" (S390_lowcore.user_asce) );
-#endif /* __s390x__ */
-        }
+       pgd_t *shadow_pgd = get_shadow_pgd(next->pgd);
+
+       if (prev != next) {
+               S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) |
+                                        PGTABLE_BITS;
+               if (shadow_pgd) {
+                       /* Load primary/secondary space page table origin. */
+                       S390_lowcore.user_exec_asce =
+                               (__pa(shadow_pgd) & PAGE_MASK) | PGTABLE_BITS;
+                       asm volatile(LCTL_OPCODE" 1,1,%0\n"
+                                    LCTL_OPCODE" 7,7,%1"
+                                    : : "m" (S390_lowcore.user_exec_asce),
+                                        "m" (S390_lowcore.user_asce) );
+               } else if (switch_amode) {
+                       /* Load primary space page table origin. */
+                       asm volatile(LCTL_OPCODE" 1,1,%0"
+                                    : : "m" (S390_lowcore.user_asce) );
+               } else
+                       /* Load home space page table origin. */
+                       asm volatile(LCTL_OPCODE" 13,13,%0"
+                                    : : "m" (S390_lowcore.user_asce) );
+       }
        cpu_set(smp_processor_id(), next->cpu_vm_mask);
 }
 
@@ -51,4 +67,4 @@ static inline void activate_mm(struct mm_struct *prev,
        set_fs(current->thread.mm_segment);
 }
 
-#endif
+#endif /* __S390_MMU_CONTEXT_H */
index 0707a7e2fc16dacb2fadc435dac8d50b2985a40a..56c8a6c80e2e18183b6bc4c11c0b53771bcee9f5 100644 (file)
@@ -47,6 +47,17 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 
        if (!pgd)
                return NULL;
+       if (s390_noexec) {
+               pgd_t *shadow_pgd = (pgd_t *)
+                       __get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER);
+               struct page *page = virt_to_page(pgd);
+
+               if (!shadow_pgd) {
+                       free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
+                       return NULL;
+               }
+               page->lru.next = (void *) shadow_pgd;
+       }
        for (i = 0; i < PTRS_PER_PGD; i++)
 #ifndef __s390x__
                pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE));
@@ -58,6 +69,10 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 
 static inline void pgd_free(pgd_t *pgd)
 {
+       pgd_t *shadow_pgd = get_shadow_pgd(pgd);
+
+       if (shadow_pgd)
+               free_pages((unsigned long) shadow_pgd, PGD_ALLOC_ORDER);
        free_pages((unsigned long) pgd, PGD_ALLOC_ORDER);
 }
 
@@ -71,6 +86,7 @@ static inline void pgd_free(pgd_t *pgd)
 #define pmd_free(x)                     do { } while (0)
 #define __pmd_free_tlb(tlb,x)          do { } while (0)
 #define pgd_populate(mm, pmd, pte)      BUG()
+#define pgd_populate_kernel(mm, pmd, pte)      BUG()
 #else /* __s390x__ */
 static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 {
@@ -79,6 +95,17 @@ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 
        if (!pmd)
                return NULL;
+       if (s390_noexec) {
+               pmd_t *shadow_pmd = (pmd_t *)
+                       __get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER);
+               struct page *page = virt_to_page(pmd);
+
+               if (!shadow_pmd) {
+                       free_pages((unsigned long) pmd, PMD_ALLOC_ORDER);
+                       return NULL;
+               }
+               page->lru.next = (void *) shadow_pmd;
+       }
        for (i=0; i < PTRS_PER_PMD; i++)
                pmd_clear(pmd + i);
        return pmd;
@@ -86,6 +113,10 @@ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 
 static inline void pmd_free (pmd_t *pmd)
 {
+       pmd_t *shadow_pmd = get_shadow_pmd(pmd);
+
+       if (shadow_pmd)
+               free_pages((unsigned long) shadow_pmd, PMD_ALLOC_ORDER);
        free_pages((unsigned long) pmd, PMD_ALLOC_ORDER);
 }
 
@@ -95,11 +126,22 @@ static inline void pmd_free (pmd_t *pmd)
                pmd_free(pmd);                  \
         } while (0)
 
-static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+static inline void
+pgd_populate_kernel(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
 {
        pgd_val(*pgd) = _PGD_ENTRY | __pa(pmd);
 }
 
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+{
+       pgd_t *shadow_pgd = get_shadow_pgd(pgd);
+       pmd_t *shadow_pmd = get_shadow_pmd(pmd);
+
+       if (shadow_pgd && shadow_pmd)
+               pgd_populate_kernel(mm, shadow_pgd, shadow_pmd);
+       pgd_populate_kernel(mm, pgd, pmd);
+}
+
 #endif /* __s390x__ */
 
 static inline void 
@@ -119,7 +161,13 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
 static inline void
 pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page)
 {
-       pmd_populate_kernel(mm, pmd, (pte_t *)page_to_phys(page));
+       pte_t *pte = (pte_t *)page_to_phys(page);
+       pmd_t *shadow_pmd = get_shadow_pmd(pmd);
+       pte_t *shadow_pte = get_shadow_pte(pte);
+
+       pmd_populate_kernel(mm, pmd, pte);
+       if (shadow_pmd && shadow_pte)
+               pmd_populate_kernel(mm, shadow_pmd, shadow_pte);
 }
 
 /*
@@ -133,6 +181,17 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long vmaddr)
 
        if (!pte)
                return NULL;
+       if (s390_noexec) {
+               pte_t *shadow_pte = (pte_t *)
+                       __get_free_page(GFP_KERNEL|__GFP_REPEAT);
+               struct page *page = virt_to_page(pte);
+
+               if (!shadow_pte) {
+                       free_page((unsigned long) pte);
+                       return NULL;
+               }
+               page->lru.next = (void *) shadow_pte;
+       }
        for (i=0; i < PTRS_PER_PTE; i++) {
                pte_clear(mm, vmaddr, pte + i);
                vmaddr += PAGE_SIZE;
@@ -151,14 +210,30 @@ pte_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 
 static inline void pte_free_kernel(pte_t *pte)
 {
-        free_page((unsigned long) pte);
+       pte_t *shadow_pte = get_shadow_pte(pte);
+
+       if (shadow_pte)
+               free_page((unsigned long) shadow_pte);
+       free_page((unsigned long) pte);
 }
 
 static inline void pte_free(struct page *pte)
 {
-        __free_page(pte);
+       struct page *shadow_page = get_shadow_page(pte);
+
+       if (shadow_page)
+               __free_page(shadow_page);
+       __free_page(pte);
 }
 
-#define __pte_free_tlb(tlb,pte) tlb_remove_page(tlb,pte)
+#define __pte_free_tlb(tlb, pte)                                       \
+({                                                                     \
+       struct mmu_gather *__tlb = (tlb);                               \
+       struct page *__pte = (pte);                                     \
+       struct page *shadow_page = get_shadow_page(__pte);              \
+       if (shadow_page)                                                \
+               tlb_remove_page(__tlb, shadow_page);                    \
+       tlb_remove_page(__tlb, __pte);                                  \
+})
 
 #endif /* _S390_PGALLOC_H */
index ae61aca5d483e25a5242a18ca69718de142c7d9c..13c16546eff5c728d577366db2e8758201578e51 100644 (file)
@@ -40,6 +40,7 @@ struct mm_struct;
 
 extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
 extern void paging_init(void);
+extern void vmem_map_init(void);
 
 /*
  * The S390 doesn't have any external MMU info: the kernel page
@@ -223,6 +224,8 @@ extern unsigned long vmalloc_end;
 #define _PAGE_TYPE_FILE                0x601   /* bit 0x002 is used for offset !! */
 #define _PAGE_TYPE_RO          0x200
 #define _PAGE_TYPE_RW          0x000
+#define _PAGE_TYPE_EX_RO       0x202
+#define _PAGE_TYPE_EX_RW       0x002
 
 /*
  * PTE type bits are rather complicated. handle_pte_fault uses pte_present,
@@ -243,11 +246,13 @@ extern unsigned long vmalloc_end;
  * _PAGE_TYPE_FILE     11?1   ->   11?1
  * _PAGE_TYPE_RO       0100   ->   1100
  * _PAGE_TYPE_RW       0000   ->   1000
+ * _PAGE_TYPE_EX_RO    0110   ->   1110
+ * _PAGE_TYPE_EX_RW    0010   ->   1010
  *
- * pte_none is true for bits combinations 1000, 1100
+ * pte_none is true for bits combinations 1000, 1010, 1100, 1110
  * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001
  * pte_file is true for bits combinations 1101, 1111
- * swap pte is 1011 and 0001, 0011, 0101, 0111, 1010 and 1110 are invalid.
+ * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid.
  */
 
 #ifndef __s390x__
@@ -312,33 +317,100 @@ extern unsigned long vmalloc_end;
 #define PAGE_NONE      __pgprot(_PAGE_TYPE_NONE)
 #define PAGE_RO                __pgprot(_PAGE_TYPE_RO)
 #define PAGE_RW                __pgprot(_PAGE_TYPE_RW)
+#define PAGE_EX_RO     __pgprot(_PAGE_TYPE_EX_RO)
+#define PAGE_EX_RW     __pgprot(_PAGE_TYPE_EX_RW)
 
 #define PAGE_KERNEL    PAGE_RW
 #define PAGE_COPY      PAGE_RO
 
 /*
- * The S390 can't do page protection for execute, and considers that the
- * same are read. Also, write permissions imply read permissions. This is
- * the closest we can get..
+ * Dependent on the EXEC_PROTECT option s390 can do execute protection.
+ * Write permission always implies read permission. In theory with a
+ * primary/secondary page table execute only can be implemented but
+ * it would cost an additional bit in the pte to distinguish all the
+ * different pte types. To avoid that execute permission currently
+ * implies read permission as well.
  */
          /*xwr*/
 #define __P000 PAGE_NONE
 #define __P001 PAGE_RO
 #define __P010 PAGE_RO
 #define __P011 PAGE_RO
-#define __P100 PAGE_RO
-#define __P101 PAGE_RO
-#define __P110 PAGE_RO
-#define __P111 PAGE_RO
+#define __P100 PAGE_EX_RO
+#define __P101 PAGE_EX_RO
+#define __P110 PAGE_EX_RO
+#define __P111 PAGE_EX_RO
 
 #define __S000 PAGE_NONE
 #define __S001 PAGE_RO
 #define __S010 PAGE_RW
 #define __S011 PAGE_RW
-#define __S100 PAGE_RO
-#define __S101 PAGE_RO
-#define __S110 PAGE_RW
-#define __S111 PAGE_RW
+#define __S100 PAGE_EX_RO
+#define __S101 PAGE_EX_RO
+#define __S110 PAGE_EX_RW
+#define __S111 PAGE_EX_RW
+
+#ifndef __s390x__
+# define PMD_SHADOW_SHIFT      1
+# define PGD_SHADOW_SHIFT      1
+#else /* __s390x__ */
+# define PMD_SHADOW_SHIFT      2
+# define PGD_SHADOW_SHIFT      2
+#endif /* __s390x__ */
+
+static inline struct page *get_shadow_page(struct page *page)
+{
+       if (s390_noexec && !list_empty(&page->lru))
+               return virt_to_page(page->lru.next);
+       return NULL;
+}
+
+static inline pte_t *get_shadow_pte(pte_t *ptep)
+{
+       unsigned long pteptr = (unsigned long) (ptep);
+
+       if (s390_noexec) {
+               unsigned long offset = pteptr & (PAGE_SIZE - 1);
+               void *addr = (void *) (pteptr ^ offset);
+               struct page *page = virt_to_page(addr);
+               if (!list_empty(&page->lru))
+                       return (pte_t *) ((unsigned long) page->lru.next |
+                                                               offset);
+       }
+       return NULL;
+}
+
+static inline pmd_t *get_shadow_pmd(pmd_t *pmdp)
+{
+       unsigned long pmdptr = (unsigned long) (pmdp);
+
+       if (s390_noexec) {
+               unsigned long offset = pmdptr &
+                               ((PAGE_SIZE << PMD_SHADOW_SHIFT) - 1);
+               void *addr = (void *) (pmdptr ^ offset);
+               struct page *page = virt_to_page(addr);
+               if (!list_empty(&page->lru))
+                       return (pmd_t *) ((unsigned long) page->lru.next |
+                                                               offset);
+       }
+       return NULL;
+}
+
+static inline pgd_t *get_shadow_pgd(pgd_t *pgdp)
+{
+       unsigned long pgdptr = (unsigned long) (pgdp);
+
+       if (s390_noexec) {
+               unsigned long offset = pgdptr &
+                               ((PAGE_SIZE << PGD_SHADOW_SHIFT) - 1);
+               void *addr = (void *) (pgdptr ^ offset);
+               struct page *page = virt_to_page(addr);
+               if (!list_empty(&page->lru))
+                       return (pgd_t *) ((unsigned long) page->lru.next |
+                                                               offset);
+       }
+       return NULL;
+}
 
 /*
  * Certain architectures need to do special things when PTEs
@@ -347,7 +419,16 @@ extern unsigned long vmalloc_end;
  */
 static inline void set_pte(pte_t *pteptr, pte_t pteval)
 {
+       pte_t *shadow_pte = get_shadow_pte(pteptr);
+
        *pteptr = pteval;
+       if (shadow_pte) {
+               if (!(pte_val(pteval) & _PAGE_INVALID) &&
+                   (pte_val(pteval) & _PAGE_SWX))
+                       pte_val(*shadow_pte) = pte_val(pteval) | _PAGE_RO;
+               else
+                       pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
+       }
 }
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
@@ -465,7 +546,7 @@ static inline int pte_read(pte_t pte)
 
 static inline void pgd_clear(pgd_t * pgdp)      { }
 
-static inline void pmd_clear(pmd_t * pmdp)
+static inline void pmd_clear_kernel(pmd_t * pmdp)
 {
        pmd_val(pmdp[0]) = _PAGE_TABLE_INV;
        pmd_val(pmdp[1]) = _PAGE_TABLE_INV;
@@ -473,24 +554,55 @@ static inline void pmd_clear(pmd_t * pmdp)
        pmd_val(pmdp[3]) = _PAGE_TABLE_INV;
 }
 
+static inline void pmd_clear(pmd_t * pmdp)
+{
+       pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
+
+       pmd_clear_kernel(pmdp);
+       if (shadow_pmd)
+               pmd_clear_kernel(shadow_pmd);
+}
+
 #else /* __s390x__ */
 
-static inline void pgd_clear(pgd_t * pgdp)
+static inline void pgd_clear_kernel(pgd_t * pgdp)
 {
        pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY;
 }
 
-static inline void pmd_clear(pmd_t * pmdp)
+static inline void pgd_clear(pgd_t * pgdp)
+{
+       pgd_t *shadow_pgd = get_shadow_pgd(pgdp);
+
+       pgd_clear_kernel(pgdp);
+       if (shadow_pgd)
+               pgd_clear_kernel(shadow_pgd);
+}
+
+static inline void pmd_clear_kernel(pmd_t * pmdp)
 {
        pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
        pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
 }
 
+static inline void pmd_clear(pmd_t * pmdp)
+{
+       pmd_t *shadow_pmd = get_shadow_pmd(pmdp);
+
+       pmd_clear_kernel(pmdp);
+       if (shadow_pmd)
+               pmd_clear_kernel(shadow_pmd);
+}
+
 #endif /* __s390x__ */
 
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
+       pte_t *shadow_pte = get_shadow_pte(ptep);
+
        pte_val(*ptep) = _PAGE_TYPE_EMPTY;
+       if (shadow_pte)
+               pte_val(*shadow_pte) = _PAGE_TYPE_EMPTY;
 }
 
 /*
@@ -608,8 +720,11 @@ ptep_clear_flush(struct vm_area_struct *vma,
                 unsigned long address, pte_t *ptep)
 {
        pte_t pte = *ptep;
+       pte_t *shadow_pte = get_shadow_pte(ptep);
 
        __ptep_ipte(address, ptep);
+       if (shadow_pte)
+               __ptep_ipte(address, shadow_pte);
        return pte;
 }
 
index cbbedc63ba25bac653aba4363ea5e1c6c2822fbb..4c1b739403519839aa8a0b50d37191e66e07816f 100644 (file)
@@ -50,6 +50,7 @@ struct cpuinfo_S390
         unsigned long pgtable_cache_sz;
 };
 
+extern void s390_adjust_jiffies(void);
 extern void print_cpu_info(struct cpuinfo_S390 *);
 
 /* Lazy FPU handling on uni-processor */
@@ -144,7 +145,8 @@ struct stack_frame {
 #ifndef __s390x__
 
 #define start_thread(regs, new_psw, new_stackp) do {            \
-        regs->psw.mask  = PSW_USER_BITS;                        \
+       set_fs(USER_DS);                                        \
+       regs->psw.mask  = psw_user_bits;                        \
         regs->psw.addr  = new_psw | PSW_ADDR_AMODE;             \
         regs->gprs[15]  = new_stackp ;                          \
 } while (0)
@@ -152,13 +154,15 @@ struct stack_frame {
 #else /* __s390x__ */
 
 #define start_thread(regs, new_psw, new_stackp) do {            \
-        regs->psw.mask  = PSW_USER_BITS;                        \
+       set_fs(USER_DS);                                        \
+       regs->psw.mask  = psw_user_bits;                        \
         regs->psw.addr  = new_psw;                              \
         regs->gprs[15]  = new_stackp;                           \
 } while (0)
 
 #define start_thread31(regs, new_psw, new_stackp) do {          \
-       regs->psw.mask  = PSW_USER32_BITS;                      \
+       set_fs(USER_DS);                                        \
+       regs->psw.mask  = psw_user32_bits;                      \
         regs->psw.addr  = new_psw;                              \
         regs->gprs[15]  = new_stackp;                           \
 } while (0)
@@ -201,9 +205,8 @@ unsigned long get_wchan(struct task_struct *p);
 static inline void cpu_relax(void)
 {
        if (MACHINE_HAS_DIAG44)
-               asm volatile("diag 0,0,68" : : : "memory");
-       else
-               barrier();
+               asm volatile("diag 0,0,68");
+       barrier();
 }
 
 /*
@@ -327,6 +330,18 @@ static inline void disabled_wait(unsigned long code)
 #endif /* __s390x__ */
 }
 
+/*
+ * Basic Machine Check/Program Check Handler.
+ */
+
+extern void s390_base_mcck_handler(void);
+extern void s390_base_pgm_handler(void);
+extern void s390_base_ext_handler(void);
+
+extern void (*s390_base_mcck_handler_fn)(void);
+extern void (*s390_base_pgm_handler_fn)(void);
+extern void (*s390_base_ext_handler_fn)(void);
+
 /*
  * CPU idle notifier chain.
  */
index 7b768c5c68a8226b43cffbfb44ce7f9ed9aa4615..fa6ca87080e804496575273a67801aa648536345 100644 (file)
@@ -266,17 +266,12 @@ typedef struct
 #define PSW_ASC_SECONDARY      0x0000800000000000UL
 #define PSW_ASC_HOME           0x0000C00000000000UL
 
-#define PSW_USER32_BITS (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
-                        PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
-                        PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
+extern long psw_user32_bits;
 
 #endif /* __s390x__ */
 
-#define PSW_KERNEL_BITS        (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \
-                        PSW_MASK_MCHECK | PSW_DEFAULT_KEY)
-#define PSW_USER_BITS  (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
-                        PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
-                        PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
+extern long psw_kernel_bits;
+extern long psw_user_bits;
 
 /* This macro merges a NEW PSW mask specified by the user into
    the currently active PSW mask CURRENT, modifying only those
index 532e65a2aafc0a7e031c054b976e5436bc84e0aa..f584f4a525814821ea25a9a061ca5dc0d5e03df6 100644 (file)
@@ -18,7 +18,4 @@ struct reset_call {
 extern void register_reset_call(struct reset_call *reset);
 extern void unregister_reset_call(struct reset_call *reset);
 extern void s390_reset_system(void);
-extern void (*s390_reset_mcck_handler)(void);
-extern void (*s390_reset_pgm_handler)(void);
-
 #endif /* _ASM_S390_RESET_H */
diff --git a/include/asm-s390/sclp.h b/include/asm-s390/sclp.h
new file mode 100644 (file)
index 0000000..468b970
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  include/asm-s390/sclp.h
+ *
+ *    Copyright IBM Corp. 2007
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_SCLP_H
+#define _ASM_S390_SCLP_H
+
+#include <linux/types.h>
+
+struct sccb_header {
+       u16     length;
+       u8      function_code;
+       u8      control_mask[3];
+       u16     response_code;
+} __attribute__((packed));
+
+#define LOADPARM_LEN 8
+
+struct sclp_readinfo_sccb {
+       struct  sccb_header header;     /* 0-7 */
+       u16     rnmax;                  /* 8-9 */
+       u8      rnsize;                 /* 10 */
+       u8      _reserved0[24 - 11];    /* 11-23 */
+       u8      loadparm[LOADPARM_LEN]; /* 24-31 */
+       u8      _reserved1[91 - 32];    /* 32-90 */
+       u8      flags;                  /* 91 */
+       u8      _reserved2[100 - 92];   /* 92-99 */
+       u32     rnsize2;                /* 100-103 */
+       u64     rnmax2;                 /* 104-111 */
+       u8      _reserved3[4096 - 112]; /* 112-4095 */
+} __attribute__((packed, aligned(4096)));
+
+extern struct sclp_readinfo_sccb s390_readinfo_sccb;
+extern void sclp_readinfo_early(void);
+
+#endif /* _ASM_S390_SCLP_H */
index 3a0b8ffeab7af2cf1c6e6cafb2e709e97319ae2e..1c5a2c4ccdad29af3ccb5c0ed4436b79522cf128 100644 (file)
@@ -3,4 +3,6 @@
 
 #include <asm-generic/sections.h>
 
+extern char _eshared[];
+
 #endif
index 9574fe80a04667d89c951adfd8c226084f0e242f..3388bb52597cb79593efa30053c882cf66be9bee 100644 (file)
@@ -42,6 +42,18 @@ struct mem_chunk {
 
 extern struct mem_chunk memory_chunk[];
 
+#ifdef CONFIG_S390_SWITCH_AMODE
+extern unsigned int switch_amode;
+#else
+#define switch_amode   (0)
+#endif
+
+#ifdef CONFIG_S390_EXEC_PROTECT
+extern unsigned int s390_noexec;
+#else
+#define s390_noexec    (0)
+#endif
+
 /*
  * Machine features detected in head.S
  */
@@ -74,6 +86,9 @@ extern unsigned int console_mode;
 extern unsigned int console_devno;
 extern unsigned int console_irq;
 
+extern char vmhalt_cmd[];
+extern char vmpoff_cmd[];
+
 #define CONSOLE_IS_UNDEFINED   (console_mode == 0)
 #define CONSOLE_IS_SCLP                (console_mode == 1)
 #define CONSOLE_IS_3215                (console_mode == 2)
@@ -141,13 +156,19 @@ struct ipl_parameter_block {
 extern u32 ipl_flags;
 extern u16 ipl_devno;
 
-void do_reipl(void);
+extern void do_reipl(void);
+extern void ipl_save_parameters(void);
 
 enum {
        IPL_DEVNO_VALID = 1,
        IPL_PARMBLOCK_VALID = 2,
+       IPL_NSS_VALID = 4,
 };
 
+#define NSS_NAME_SIZE  8
+
+extern char kernel_nss_name[];
+
 #define IPL_PARMBLOCK_START    ((struct ipl_parameter_block *) \
                                 IPL_PARMBLOCK_ORIGIN)
 #define IPL_PARMBLOCK_SIZE     (IPL_PARMBLOCK_START->hdr.len)
similarity index 91%
rename from arch/s390/math-emu/sfp-util.h
rename to include/asm-s390/sfp-util.h
index 5b6ca4570ea41e6b44aba008cf0ce520f7a86580..8cabcd23d976c8136ba0df486858c42c31e91059 100644 (file)
 })
 
 #define udiv_qrnnd(q, r, n1, n0, d)                    \
-  do { unsigned long __r;                              \
+  do { unsigned int __r;                               \
     (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));                \
     (r) = __r;                                         \
   } while (0)
-extern unsigned long __udiv_qrnnd (unsigned long *, unsigned long,
-                                  unsigned long , unsigned long);
+extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
+                                  unsigned int , unsigned int);
 
 #define UDIV_NEEDS_NORMALIZATION 0
 
index 7097c96ed026ff41fb9b4467be56e6c18bdac9df..b957e4cda46466073a93d4c63e53968da3d6a825 100644 (file)
@@ -31,6 +31,10 @@ typedef struct
        __u16      cpu;
 } sigp_info;
 
+extern void machine_restart_smp(char *);
+extern void machine_halt_smp(void);
+extern void machine_power_off_smp(void);
+
 extern void smp_setup_cpu_possible_map(void);
 extern int smp_call_function_on(void (*func) (void *info), void *info,
                                int nonatomic, int wait, int cpu);
@@ -106,7 +110,7 @@ smp_call_function_on(void (*func) (void *info), void *info,
 static inline void smp_send_stop(void)
 {
        /* Disable all interrupts/machine checks */
-       __load_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK);
+       __load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK);
 }
 
 #define smp_cpu_not_running(cpu)       1
index bd0b05ae87d248b5badf16ec3e0e5a194c3a47fe..bbe137c3ed6980423e74f24e548ad95f8e5ac000 100644 (file)
@@ -373,8 +373,8 @@ __set_psw_mask(unsigned long mask)
        __load_psw_mask(mask | (__raw_local_irq_stosm(0x00) & ~(-1UL >> 8)));
 }
 
-#define local_mcck_enable()  __set_psw_mask(PSW_KERNEL_BITS)
-#define local_mcck_disable() __set_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK)
+#define local_mcck_enable()  __set_psw_mask(psw_kernel_bits)
+#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK)
 
 #ifdef CONFIG_SMP
 
index f1d66ba0deef4123be4565df1a9492d859fc0d39..884fba48f1ff522e3fecd09cbf04deaeb7ca69cb 100644 (file)
@@ -1,11 +1,11 @@
 /*************************************************************************
  *
  * tape390.h
- *         enables user programs to display messages on the tape device
+ *        enables user programs to display messages and control encryption
+ *        on s390 tape devices
  *
- *  S390 and zSeries version
- *         Copyright (C) 2001 IBM Corporation
- *         Author(s): Despina Papadopoulou <despina_p@de.ibm.com>
+ *        Copyright IBM Corp. 2001,2006
+ *        Author(s): Michael Holzheu <holzheu@de.ibm.com>
  *
  *************************************************************************/
 
@@ -36,4 +36,68 @@ typedef struct display_struct {
         char message2[8];
 } display_struct;
 
+/*
+ * Tape encryption support
+ */
+
+struct tape390_crypt_info {
+       char capability;
+       char status;
+       char medium_status;
+} __attribute__ ((packed));
+
+
+/* Macros for "capable" field */
+#define TAPE390_CRYPT_SUPPORTED_MASK 0x01
+#define TAPE390_CRYPT_SUPPORTED(x) \
+       ((x.capability & TAPE390_CRYPT_SUPPORTED_MASK))
+
+/* Macros for "status" field */
+#define TAPE390_CRYPT_ON_MASK 0x01
+#define TAPE390_CRYPT_ON(x) (((x.status) & TAPE390_CRYPT_ON_MASK))
+
+/* Macros for "medium status" field */
+#define TAPE390_MEDIUM_LOADED_MASK 0x01
+#define TAPE390_MEDIUM_ENCRYPTED_MASK 0x02
+#define TAPE390_MEDIUM_ENCRYPTED(x) \
+       (((x.medium_status) & TAPE390_MEDIUM_ENCRYPTED_MASK))
+#define TAPE390_MEDIUM_LOADED(x) \
+       (((x.medium_status) & TAPE390_MEDIUM_LOADED_MASK))
+
+/*
+ * The TAPE390_CRYPT_SET ioctl is used to switch on/off encryption.
+ * The "encryption_capable" and "tape_status" fields are ignored for this ioctl!
+ */
+#define TAPE390_CRYPT_SET _IOW('d', 2, struct tape390_crypt_info)
+
+/*
+ * The TAPE390_CRYPT_QUERY ioctl is used to query the encryption state.
+ */
+#define TAPE390_CRYPT_QUERY _IOR('d', 3, struct tape390_crypt_info)
+
+/* Values for "kekl1/2_type" and "kekl1/2_type_on_tape" fields */
+#define TAPE390_KEKL_TYPE_NONE 0
+#define TAPE390_KEKL_TYPE_LABEL 1
+#define TAPE390_KEKL_TYPE_HASH 2
+
+struct tape390_kekl {
+       unsigned char type;
+       unsigned char type_on_tape;
+       char label[65];
+} __attribute__ ((packed));
+
+struct tape390_kekl_pair {
+       struct tape390_kekl kekl[2];
+} __attribute__ ((packed));
+
+/*
+ * The TAPE390_KEKL_SET ioctl is used to set Key Encrypting Key labels.
+ */
+#define TAPE390_KEKL_SET _IOW('d', 4, struct tape390_kekl_pair)
+
+/*
+ * The TAPE390_KEKL_QUERY ioctl is used to query Key Encrypting Key labels.
+ */
+#define TAPE390_KEKL_QUERY _IOR('d', 5, struct tape390_kekl_pair)
+
 #endif 
index 30e5cbe570f2db3d29f73e282a6ef10bd57b4063..adb34860a543e42abc6b73ddcaf71b04dbbaf76b 100644 (file)
@@ -45,6 +45,9 @@ extern void add_virt_timer_periodic(void *new);
 extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires);
 extern int del_virt_timer(struct vtimer_list *timer);
 
+extern void init_cpu_vtimer(void);
+extern void vtime_init(void);
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_S390_TIMER_H */
index 4df4a41029a32d22bb5c5ce618c8743637f2db77..98229db243141ba189a0f75927da5a351af7d992 100644 (file)
 #ifndef _ASM_S390_TIMEX_H
 #define _ASM_S390_TIMEX_H
 
+/* Inline functions for clock register access. */
+static inline int set_clock(__u64 time)
+{
+       int cc;
+
+       asm volatile(
+               "   sck   0(%2)\n"
+               "   ipm   %0\n"
+               "   srl   %0,28\n"
+               : "=d" (cc) : "m" (time), "a" (&time) : "cc");
+       return cc;
+}
+
+static inline int store_clock(__u64 *time)
+{
+       int cc;
+
+       asm volatile(
+               "   stck  0(%2)\n"
+               "   ipm   %0\n"
+               "   srl   %0,28\n"
+               : "=d" (cc), "=m" (*time) : "a" (time) : "cc");
+       return cc;
+}
+
+static inline void set_clock_comparator(__u64 time)
+{
+       asm volatile("sckc 0(%1)" : : "m" (time), "a" (&time));
+}
+
+static inline void store_clock_comparator(__u64 *time)
+{
+       asm volatile("stckc 0(%1)" : "=m" (*time) : "a" (time));
+}
+
 #define CLOCK_TICK_RATE        1193180 /* Underlying HZ */
 
 typedef unsigned long long cycles_t;
@@ -27,9 +62,24 @@ static inline unsigned long long get_clock (void)
        return clk;
 }
 
+static inline void get_clock_extended(void *dest)
+{
+       typedef struct { unsigned long long clk[2]; } __clock_t;
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
+       asm volatile("stcke %0" : "=Q" (*((__clock_t *)dest)) : : "cc");
+#else /* __GNUC__ */
+       asm volatile("stcke 0(%1)" : "=m" (*((__clock_t *)dest))
+                                  : "a" ((__clock_t *)dest) : "cc");
+#endif /* __GNUC__ */
+}
+
 static inline cycles_t get_cycles(void)
 {
        return (cycles_t) get_clock() >> 2;
 }
 
+int get_sync_clock(unsigned long long *clock);
+void init_cpu_timer(void);
+
 #endif
index fa4dc916a9bfe5de40fd2bb5f1bc31dd8015dadb..66793f55c8b2dea7b61f8a7aeada359e252afa22 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/mm.h>
 #include <asm/processor.h>
+#include <asm/pgalloc.h>
 
 /*
  * TLB flushing:
@@ -102,6 +103,14 @@ static inline void __flush_tlb_mm(struct mm_struct * mm)
        if (unlikely(cpus_empty(mm->cpu_vm_mask)))
                return;
        if (MACHINE_HAS_IDTE) {
+               pgd_t *shadow_pgd = get_shadow_pgd(mm->pgd);
+
+               if (shadow_pgd) {
+                       asm volatile(
+                               "       .insn   rrf,0xb98e0000,0,%0,%1,0"
+                               : : "a" (2048),
+                               "a" (__pa(shadow_pgd) & PAGE_MASK) : "cc" );
+               }
                asm volatile(
                        "       .insn   rrf,0xb98e0000,0,%0,%1,0"
                        : : "a" (2048), "a" (__pa(mm->pgd)&PAGE_MASK) : "cc");
index 73ac4e82217bd21d3ebaf9b8956ac7f9e915e50c..0235970278f0574516ca7638e08737ce58c3ef3c 100644 (file)
@@ -90,6 +90,8 @@ struct uaccess_ops {
 extern struct uaccess_ops uaccess;
 extern struct uaccess_ops uaccess_std;
 extern struct uaccess_ops uaccess_mvcos;
+extern struct uaccess_ops uaccess_mvcos_switch;
+extern struct uaccess_ops uaccess_pt;
 
 static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
 {
index ba94ab3d2673572d6c6eb07a3bd1bb1a840174ef..ab913ffcad569201bb921bc6e7c4bfc1db5f450b 100644 (file)
@@ -1,6 +1,5 @@
 #ifndef _ASM_SWIOTLB_H
-#define _ASM_SWTIOLB_H 1
-
+#define _ASM_SWIOTLB_H 1
 
 #include <asm/dma-mapping.h>
 
@@ -45,6 +44,7 @@ extern void swiotlb_init(void);
 extern int swiotlb_force;
 
 #ifdef CONFIG_SWIOTLB
+#define SWIOTLB_ARCH_NEED_ALLOC
 extern int swiotlb;
 #else
 #define swiotlb 0
@@ -52,4 +52,6 @@ extern int swiotlb;
 
 extern void pci_swiotlb_init(void);
 
-#endif /* _ASM_SWTIOLB_H */
+static inline void dma_mark_clean(void *addr, size_t size) {}
+
+#endif /* _ASM_SWIOTLB_H */
index 8e4dbb51fc702f6703e520bfbae497c60aa80d26..50d568ec178a67aa1dd6937935a249b354589125 100644 (file)
@@ -1,10 +1,8 @@
+#ifndef __HID_DEBUG_H
+#define __HID_DEBUG_H
+
 /*
- * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
- *
- *  (c) 1999 Andreas Gal               <gal@cs.uni-magdeburg.de>
- *  (c) 2000-2001 Vojtech Pavlik       <vojtech@ucw.cz>
- *
- *  Some debug stuff for the HID parser.
+ *  Copyright (c) 2007 Jiri Kosina
  */
 
 /*
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  */
 
-#include <linux/input.h>
-
-struct hid_usage_entry {
-       unsigned  page;
-       unsigned  usage;
-       char     *description;
-};
-
-static const struct hid_usage_entry hid_usage_table[] = {
-  {  0,      0, "Undefined" },
-  {  1,      0, "GenericDesktop" },
-    {0, 0x01, "Pointer"},
-    {0, 0x02, "Mouse"},
-    {0, 0x04, "Joystick"},
-    {0, 0x05, "GamePad"},
-    {0, 0x06, "Keyboard"},
-    {0, 0x07, "Keypad"},
-    {0, 0x08, "MultiAxis"},
-      {0, 0x30, "X"},
-      {0, 0x31, "Y"},
-      {0, 0x32, "Z"},
-      {0, 0x33, "Rx"},
-      {0, 0x34, "Ry"},
-      {0, 0x35, "Rz"},
-      {0, 0x36, "Slider"},
-      {0, 0x37, "Dial"},
-      {0, 0x38, "Wheel"},
-      {0, 0x39, "HatSwitch"},
-    {0, 0x3a, "CountedBuffer"},
-      {0, 0x3b, "ByteCount"},
-      {0, 0x3c, "MotionWakeup"},
-      {0, 0x3d, "Start"},
-      {0, 0x3e, "Select"},
-      {0, 0x40, "Vx"},
-      {0, 0x41, "Vy"},
-      {0, 0x42, "Vz"},
-      {0, 0x43, "Vbrx"},
-      {0, 0x44, "Vbry"},
-      {0, 0x45, "Vbrz"},
-      {0, 0x46, "Vno"},
-    {0, 0x80, "SystemControl"},
-      {0, 0x81, "SystemPowerDown"},
-      {0, 0x82, "SystemSleep"},
-      {0, 0x83, "SystemWakeUp"},
-      {0, 0x84, "SystemContextMenu"},
-      {0, 0x85, "SystemMainMenu"},
-      {0, 0x86, "SystemAppMenu"},
-      {0, 0x87, "SystemMenuHelp"},
-      {0, 0x88, "SystemMenuExit"},
-      {0, 0x89, "SystemMenuSelect"},
-      {0, 0x8a, "SystemMenuRight"},
-      {0, 0x8b, "SystemMenuLeft"},
-      {0, 0x8c, "SystemMenuUp"},
-      {0, 0x8d, "SystemMenuDown"},
-      {0, 0x90, "D-PadUp"},
-      {0, 0x91, "D-PadDown"},
-      {0, 0x92, "D-PadRight"},
-      {0, 0x93, "D-PadLeft"},
-  {  2, 0, "Simulation" },
-      {0, 0xb0, "Aileron"},
-      {0, 0xb1, "AileronTrim"},
-      {0, 0xb2, "Anti-Torque"},
-      {0, 0xb3, "Autopilot"},
-      {0, 0xb4, "Chaff"},
-      {0, 0xb5, "Collective"},
-      {0, 0xb6, "DiveBrake"},
-      {0, 0xb7, "ElectronicCountermeasures"},
-      {0, 0xb8, "Elevator"},
-      {0, 0xb9, "ElevatorTrim"},
-      {0, 0xba, "Rudder"},
-      {0, 0xbb, "Throttle"},
-      {0, 0xbc, "FlightCommunications"},
-      {0, 0xbd, "FlareRelease"},
-      {0, 0xbe, "LandingGear"},
-      {0, 0xbf, "ToeBrake"},
-  {  7, 0, "Keyboard" },
-  {  8, 0, "LED" },
-      {0, 0x01, "NumLock"},
-      {0, 0x02, "CapsLock"},
-      {0, 0x03, "ScrollLock"},
-      {0, 0x04, "Compose"},
-      {0, 0x05, "Kana"},
-      {0, 0x4b, "GenericIndicator"},
-  {  9, 0, "Button" },
-  { 10, 0, "Ordinal" },
-  { 12, 0, "Consumer" },
-      {0, 0x238, "HorizontalWheel"},
-  { 13, 0, "Digitizers" },
-    {0, 0x01, "Digitizer"},
-    {0, 0x02, "Pen"},
-    {0, 0x03, "LightPen"},
-    {0, 0x04, "TouchScreen"},
-    {0, 0x05, "TouchPad"},
-    {0, 0x20, "Stylus"},
-    {0, 0x21, "Puck"},
-    {0, 0x22, "Finger"},
-    {0, 0x30, "TipPressure"},
-    {0, 0x31, "BarrelPressure"},
-    {0, 0x32, "InRange"},
-    {0, 0x33, "Touch"},
-    {0, 0x34, "UnTouch"},
-    {0, 0x35, "Tap"},
-    {0, 0x39, "TabletFunctionKey"},
-    {0, 0x3a, "ProgramChangeKey"},
-    {0, 0x3c, "Invert"},
-    {0, 0x42, "TipSwitch"},
-    {0, 0x43, "SecondaryTipSwitch"},
-    {0, 0x44, "BarrelSwitch"},
-    {0, 0x45, "Eraser"},
-    {0, 0x46, "TabletPick"},
-  { 15, 0, "PhysicalInterfaceDevice" },
-    {0, 0x00, "Undefined"},
-    {0, 0x01, "Physical_Interface_Device"},
-      {0, 0x20, "Normal"},
-    {0, 0x21, "Set_Effect_Report"},
-      {0, 0x22, "Effect_Block_Index"},
-      {0, 0x23, "Parameter_Block_Offset"},
-      {0, 0x24, "ROM_Flag"},
-      {0, 0x25, "Effect_Type"},
-        {0, 0x26, "ET_Constant_Force"},
-        {0, 0x27, "ET_Ramp"},
-        {0, 0x28, "ET_Custom_Force_Data"},
-        {0, 0x30, "ET_Square"},
-        {0, 0x31, "ET_Sine"},
-        {0, 0x32, "ET_Triangle"},
-        {0, 0x33, "ET_Sawtooth_Up"},
-        {0, 0x34, "ET_Sawtooth_Down"},
-        {0, 0x40, "ET_Spring"},
-        {0, 0x41, "ET_Damper"},
-        {0, 0x42, "ET_Inertia"},
-        {0, 0x43, "ET_Friction"},
-      {0, 0x50, "Duration"},
-      {0, 0x51, "Sample_Period"},
-      {0, 0x52, "Gain"},
-      {0, 0x53, "Trigger_Button"},
-      {0, 0x54, "Trigger_Repeat_Interval"},
-      {0, 0x55, "Axes_Enable"},
-        {0, 0x56, "Direction_Enable"},
-      {0, 0x57, "Direction"},
-      {0, 0x58, "Type_Specific_Block_Offset"},
-        {0, 0x59, "Block_Type"},
-        {0, 0x5A, "Set_Envelope_Report"},
-          {0, 0x5B, "Attack_Level"},
-          {0, 0x5C, "Attack_Time"},
-          {0, 0x5D, "Fade_Level"},
-          {0, 0x5E, "Fade_Time"},
-        {0, 0x5F, "Set_Condition_Report"},
-        {0, 0x60, "CP_Offset"},
-        {0, 0x61, "Positive_Coefficient"},
-        {0, 0x62, "Negative_Coefficient"},
-        {0, 0x63, "Positive_Saturation"},
-        {0, 0x64, "Negative_Saturation"},
-        {0, 0x65, "Dead_Band"},
-      {0, 0x66, "Download_Force_Sample"},
-      {0, 0x67, "Isoch_Custom_Force_Enable"},
-      {0, 0x68, "Custom_Force_Data_Report"},
-        {0, 0x69, "Custom_Force_Data"},
-        {0, 0x6A, "Custom_Force_Vendor_Defined_Data"},
-      {0, 0x6B, "Set_Custom_Force_Report"},
-        {0, 0x6C, "Custom_Force_Data_Offset"},
-        {0, 0x6D, "Sample_Count"},
-      {0, 0x6E, "Set_Periodic_Report"},
-        {0, 0x6F, "Offset"},
-        {0, 0x70, "Magnitude"},
-        {0, 0x71, "Phase"},
-        {0, 0x72, "Period"},
-      {0, 0x73, "Set_Constant_Force_Report"},
-        {0, 0x74, "Set_Ramp_Force_Report"},
-        {0, 0x75, "Ramp_Start"},
-        {0, 0x76, "Ramp_End"},
-      {0, 0x77, "Effect_Operation_Report"},
-        {0, 0x78, "Effect_Operation"},
-          {0, 0x79, "Op_Effect_Start"},
-          {0, 0x7A, "Op_Effect_Start_Solo"},
-          {0, 0x7B, "Op_Effect_Stop"},
-          {0, 0x7C, "Loop_Count"},
-      {0, 0x7D, "Device_Gain_Report"},
-        {0, 0x7E, "Device_Gain"},
-    {0, 0x7F, "PID_Pool_Report"},
-      {0, 0x80, "RAM_Pool_Size"},
-      {0, 0x81, "ROM_Pool_Size"},
-      {0, 0x82, "ROM_Effect_Block_Count"},
-      {0, 0x83, "Simultaneous_Effects_Max"},
-      {0, 0x84, "Pool_Alignment"},
-    {0, 0x85, "PID_Pool_Move_Report"},
-      {0, 0x86, "Move_Source"},
-      {0, 0x87, "Move_Destination"},
-      {0, 0x88, "Move_Length"},
-    {0, 0x89, "PID_Block_Load_Report"},
-      {0, 0x8B, "Block_Load_Status"},
-      {0, 0x8C, "Block_Load_Success"},
-      {0, 0x8D, "Block_Load_Full"},
-      {0, 0x8E, "Block_Load_Error"},
-      {0, 0x8F, "Block_Handle"},
-      {0, 0x90, "PID_Block_Free_Report"},
-      {0, 0x91, "Type_Specific_Block_Handle"},
-    {0, 0x92, "PID_State_Report"},
-      {0, 0x94, "Effect_Playing"},
-      {0, 0x95, "PID_Device_Control_Report"},
-        {0, 0x96, "PID_Device_Control"},
-        {0, 0x97, "DC_Enable_Actuators"},
-        {0, 0x98, "DC_Disable_Actuators"},
-        {0, 0x99, "DC_Stop_All_Effects"},
-        {0, 0x9A, "DC_Device_Reset"},
-        {0, 0x9B, "DC_Device_Pause"},
-        {0, 0x9C, "DC_Device_Continue"},
-      {0, 0x9F, "Device_Paused"},
-      {0, 0xA0, "Actuators_Enabled"},
-      {0, 0xA4, "Safety_Switch"},
-      {0, 0xA5, "Actuator_Override_Switch"},
-      {0, 0xA6, "Actuator_Power"},
-    {0, 0xA7, "Start_Delay"},
-    {0, 0xA8, "Parameter_Block_Size"},
-    {0, 0xA9, "Device_Managed_Pool"},
-    {0, 0xAA, "Shared_Parameter_Blocks"},
-    {0, 0xAB, "Create_New_Effect_Report"},
-    {0, 0xAC, "RAM_Pool_Available"},
-  { 0x84, 0, "Power Device" },
-    { 0x84, 0x02, "PresentStatus" },
-    { 0x84, 0x03, "ChangeStatus" },
-    { 0x84, 0x04, "UPS" },
-    { 0x84, 0x05, "PowerSupply" },
-    { 0x84, 0x10, "BatterySystem" },
-    { 0x84, 0x11, "BatterySystemID" },
-    { 0x84, 0x12, "Battery" },
-    { 0x84, 0x13, "BatteryID" },
-    { 0x84, 0x14, "Charger" },
-    { 0x84, 0x15, "ChargerID" },
-    { 0x84, 0x16, "PowerConverter" },
-    { 0x84, 0x17, "PowerConverterID" },
-    { 0x84, 0x18, "OutletSystem" },
-    { 0x84, 0x19, "OutletSystemID" },
-    { 0x84, 0x1a, "Input" },
-    { 0x84, 0x1b, "InputID" },
-    { 0x84, 0x1c, "Output" },
-    { 0x84, 0x1d, "OutputID" },
-    { 0x84, 0x1e, "Flow" },
-    { 0x84, 0x1f, "FlowID" },
-    { 0x84, 0x20, "Outlet" },
-    { 0x84, 0x21, "OutletID" },
-    { 0x84, 0x22, "Gang" },
-    { 0x84, 0x24, "PowerSummary" },
-    { 0x84, 0x25, "PowerSummaryID" },
-    { 0x84, 0x30, "Voltage" },
-    { 0x84, 0x31, "Current" },
-    { 0x84, 0x32, "Frequency" },
-    { 0x84, 0x33, "ApparentPower" },
-    { 0x84, 0x35, "PercentLoad" },
-    { 0x84, 0x40, "ConfigVoltage" },
-    { 0x84, 0x41, "ConfigCurrent" },
-    { 0x84, 0x43, "ConfigApparentPower" },
-    { 0x84, 0x53, "LowVoltageTransfer" },
-    { 0x84, 0x54, "HighVoltageTransfer" },
-    { 0x84, 0x56, "DelayBeforeStartup" },
-    { 0x84, 0x57, "DelayBeforeShutdown" },
-    { 0x84, 0x58, "Test" },
-    { 0x84, 0x5a, "AudibleAlarmControl" },
-    { 0x84, 0x60, "Present" },
-    { 0x84, 0x61, "Good" },
-    { 0x84, 0x62, "InternalFailure" },
-    { 0x84, 0x65, "Overload" },
-    { 0x84, 0x66, "OverCharged" },
-    { 0x84, 0x67, "OverTemperature" },
-    { 0x84, 0x68, "ShutdownRequested" },
-    { 0x84, 0x69, "ShutdownImminent" },
-    { 0x84, 0x6b, "SwitchOn/Off" },
-    { 0x84, 0x6c, "Switchable" },
-    { 0x84, 0x6d, "Used" },
-    { 0x84, 0x6e, "Boost" },
-    { 0x84, 0x73, "CommunicationLost" },
-    { 0x84, 0xfd, "iManufacturer" },
-    { 0x84, 0xfe, "iProduct" },
-    { 0x84, 0xff, "iSerialNumber" },
-  { 0x85, 0, "Battery System" },
-    { 0x85, 0x01, "SMBBatteryMode" },
-    { 0x85, 0x02, "SMBBatteryStatus" },
-    { 0x85, 0x03, "SMBAlarmWarning" },
-    { 0x85, 0x04, "SMBChargerMode" },
-    { 0x85, 0x05, "SMBChargerStatus" },
-    { 0x85, 0x06, "SMBChargerSpecInfo" },
-    { 0x85, 0x07, "SMBSelectorState" },
-    { 0x85, 0x08, "SMBSelectorPresets" },
-    { 0x85, 0x09, "SMBSelectorInfo" },
-    { 0x85, 0x29, "RemainingCapacityLimit" },
-    { 0x85, 0x2c, "CapacityMode" },
-    { 0x85, 0x42, "BelowRemainingCapacityLimit" },
-    { 0x85, 0x44, "Charging" },
-    { 0x85, 0x45, "Discharging" },
-    { 0x85, 0x4b, "NeedReplacement" },
-    { 0x85, 0x66, "RemainingCapacity" },
-    { 0x85, 0x68, "RunTimeToEmpty" },
-    { 0x85, 0x6a, "AverageTimeToFull" },
-    { 0x85, 0x83, "DesignCapacity" },
-    { 0x85, 0x85, "ManufacturerDate" },
-    { 0x85, 0x89, "iDeviceChemistry" },
-    { 0x85, 0x8b, "Rechargable" },
-    { 0x85, 0x8f, "iOEMInformation" },
-    { 0x85, 0x8d, "CapacityGranularity1" },
-    { 0x85, 0xd0, "ACPresent" },
-  /* pages 0xff00 to 0xffff are vendor-specific */
-  { 0xffff, 0, "Vendor-specific-FF" },
-  { 0, 0, NULL }
-};
-
-static void resolv_usage_page(unsigned page) {
-       const struct hid_usage_entry *p;
-
-       for (p = hid_usage_table; p->description; p++)
-               if (p->page == page) {
-                       printk("%s", p->description);
-                       return;
-               }
-       printk("%04x", page);
-}
-
-static void resolv_usage(unsigned usage) {
-       const struct hid_usage_entry *p;
-
-       resolv_usage_page(usage >> 16);
-       printk(".");
-       for (p = hid_usage_table; p->description; p++)
-               if (p->page == (usage >> 16)) {
-                       for(++p; p->description && p->usage != 0; p++)
-                               if (p->usage == (usage & 0xffff)) {
-                                       printk("%s", p->description);
-                                       return;
-                               }
-                       break;
-               }
-       printk("%04x", usage & 0xffff);
-}
-
-__inline__ static void tab(int n) {
-       while (n--) printk(" ");
-}
-
-static void hid_dump_field(struct hid_field *field, int n) {
-       int j;
-
-       if (field->physical) {
-               tab(n);
-               printk("Physical(");
-               resolv_usage(field->physical); printk(")\n");
-       }
-       if (field->logical) {
-               tab(n);
-               printk("Logical(");
-               resolv_usage(field->logical); printk(")\n");
-       }
-       tab(n); printk("Usage(%d)\n", field->maxusage);
-       for (j = 0; j < field->maxusage; j++) {
-               tab(n+2);resolv_usage(field->usage[j].hid); printk("\n");
-       }
-       if (field->logical_minimum != field->logical_maximum) {
-               tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
-               tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
-       }
-       if (field->physical_minimum != field->physical_maximum) {
-               tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
-               tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
-       }
-       if (field->unit_exponent) {
-               tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
-       }
-       if (field->unit) {
-               char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" };
-               char *units[5][8] = {
-                       { "None", "None", "None", "None", "None", "None", "None", "None" },
-                       { "None", "Centimeter", "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
-                       { "None", "Radians",    "Gram", "Seconds", "Kelvin",     "Ampere", "Candela", "None" },
-                       { "None", "Inch",       "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" },
-                       { "None", "Degrees",    "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }
-               };
-
-               int i;
-               int sys;
-                __u32 data = field->unit;
-
-               /* First nibble tells us which system we're in. */
-               sys = data & 0xf;
-               data >>= 4;
-
-               if(sys > 4) {
-                       tab(n); printk("Unit(Invalid)\n");
-               }
-               else {
-                       int earlier_unit = 0;
-
-                       tab(n); printk("Unit(%s : ", systems[sys]);
-
-                       for (i=1 ; i<sizeof(__u32)*2 ; i++) {
-                               char nibble = data & 0xf;
-                               data >>= 4;
-                               if (nibble != 0) {
-                                       if(earlier_unit++ > 0)
-                                               printk("*");
-                                       printk("%s", units[sys][i]);
-                                       if(nibble != 1) {
-                                               /* This is a _signed_ nibble(!) */
-
-                                               int val = nibble & 0x7;
-                                               if(nibble & 0x08)
-                                                       val = -((0x7 & ~val) +1);
-                                               printk("^%d", val);
-                                       }
-                               }
-                       }
-                       printk(")\n");
-               }
-       }
-       tab(n); printk("Report Size(%u)\n", field->report_size);
-       tab(n); printk("Report Count(%u)\n", field->report_count);
-       tab(n); printk("Report Offset(%u)\n", field->report_offset);
-
-       tab(n); printk("Flags( ");
-       j = field->flags;
-       printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
-       printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
-       printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
-       printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
-       printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
-       printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : "");
-       printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
-       printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
-       printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
-       printk(")\n");
-}
-
-static void __attribute__((unused)) hid_dump_device(struct hid_device *device) {
-       struct hid_report_enum *report_enum;
-       struct hid_report *report;
-       struct list_head *list;
-       unsigned i,k;
-       static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
-
-       for (i = 0; i < HID_REPORT_TYPES; i++) {
-               report_enum = device->report_enum + i;
-               list = report_enum->report_list.next;
-               while (list != &report_enum->report_list) {
-                       report = (struct hid_report *) list;
-                       tab(2);
-                       printk("%s", table[i]);
-                       if (report->id)
-                               printk("(%d)", report->id);
-                       printk("[%s]", table[report->type]);
-                       printk("\n");
-                       for (k = 0; k < report->maxfield; k++) {
-                               tab(4);
-                               printk("Field(%d)\n", k);
-                               hid_dump_field(report->field[k], 6);
-                       }
-                       list = list->next;
-               }
-       }
-}
-
-static void __attribute__((unused)) hid_dump_input(struct hid_usage *usage, __s32 value) {
-       printk("hid-debug: input ");
-       resolv_usage(usage->hid);
-       printk(" = %d\n", value);
-}
-
-
-static char *events[EV_MAX + 1] = {
-       [EV_SYN] = "Sync",                      [EV_KEY] = "Key",
-       [EV_REL] = "Relative",                  [EV_ABS] = "Absolute",
-       [EV_MSC] = "Misc",                      [EV_LED] = "LED",
-       [EV_SND] = "Sound",                     [EV_REP] = "Repeat",
-       [EV_FF] = "ForceFeedback",              [EV_PWR] = "Power",
-       [EV_FF_STATUS] = "ForceFeedbackStatus",
-};
-
-static char *syncs[2] = {
-       [SYN_REPORT] = "Report",                [SYN_CONFIG] = "Config",
-};
-static char *keys[KEY_MAX + 1] = {
-       [KEY_RESERVED] = "Reserved",            [KEY_ESC] = "Esc",
-       [KEY_1] = "1",                          [KEY_2] = "2",
-       [KEY_3] = "3",                          [KEY_4] = "4",
-       [KEY_5] = "5",                          [KEY_6] = "6",
-       [KEY_7] = "7",                          [KEY_8] = "8",
-       [KEY_9] = "9",                          [KEY_0] = "0",
-       [KEY_MINUS] = "Minus",                  [KEY_EQUAL] = "Equal",
-       [KEY_BACKSPACE] = "Backspace",          [KEY_TAB] = "Tab",
-       [KEY_Q] = "Q",                          [KEY_W] = "W",
-       [KEY_E] = "E",                          [KEY_R] = "R",
-       [KEY_T] = "T",                          [KEY_Y] = "Y",
-       [KEY_U] = "U",                          [KEY_I] = "I",
-       [KEY_O] = "O",                          [KEY_P] = "P",
-       [KEY_LEFTBRACE] = "LeftBrace",          [KEY_RIGHTBRACE] = "RightBrace",
-       [KEY_ENTER] = "Enter",                  [KEY_LEFTCTRL] = "LeftControl",
-       [KEY_A] = "A",                          [KEY_S] = "S",
-       [KEY_D] = "D",                          [KEY_F] = "F",
-       [KEY_G] = "G",                          [KEY_H] = "H",
-       [KEY_J] = "J",                          [KEY_K] = "K",
-       [KEY_L] = "L",                          [KEY_SEMICOLON] = "Semicolon",
-       [KEY_APOSTROPHE] = "Apostrophe",        [KEY_GRAVE] = "Grave",
-       [KEY_LEFTSHIFT] = "LeftShift",          [KEY_BACKSLASH] = "BackSlash",
-       [KEY_Z] = "Z",                          [KEY_X] = "X",
-       [KEY_C] = "C",                          [KEY_V] = "V",
-       [KEY_B] = "B",                          [KEY_N] = "N",
-       [KEY_M] = "M",                          [KEY_COMMA] = "Comma",
-       [KEY_DOT] = "Dot",                      [KEY_SLASH] = "Slash",
-       [KEY_RIGHTSHIFT] = "RightShift",        [KEY_KPASTERISK] = "KPAsterisk",
-       [KEY_LEFTALT] = "LeftAlt",              [KEY_SPACE] = "Space",
-       [KEY_CAPSLOCK] = "CapsLock",            [KEY_F1] = "F1",
-       [KEY_F2] = "F2",                        [KEY_F3] = "F3",
-       [KEY_F4] = "F4",                        [KEY_F5] = "F5",
-       [KEY_F6] = "F6",                        [KEY_F7] = "F7",
-       [KEY_F8] = "F8",                        [KEY_F9] = "F9",
-       [KEY_F10] = "F10",                      [KEY_NUMLOCK] = "NumLock",
-       [KEY_SCROLLLOCK] = "ScrollLock",        [KEY_KP7] = "KP7",
-       [KEY_KP8] = "KP8",                      [KEY_KP9] = "KP9",
-       [KEY_KPMINUS] = "KPMinus",              [KEY_KP4] = "KP4",
-       [KEY_KP5] = "KP5",                      [KEY_KP6] = "KP6",
-       [KEY_KPPLUS] = "KPPlus",                [KEY_KP1] = "KP1",
-       [KEY_KP2] = "KP2",                      [KEY_KP3] = "KP3",
-       [KEY_KP0] = "KP0",                      [KEY_KPDOT] = "KPDot",
-       [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd",
-       [KEY_F11] = "F11",                      [KEY_F12] = "F12",
-       [KEY_RO] = "RO",                        [KEY_KATAKANA] = "Katakana",
-       [KEY_HIRAGANA] = "HIRAGANA",            [KEY_HENKAN] = "Henkan",
-       [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan",
-       [KEY_KPJPCOMMA] = "KPJpComma",          [KEY_KPENTER] = "KPEnter",
-       [KEY_RIGHTCTRL] = "RightCtrl",          [KEY_KPSLASH] = "KPSlash",
-       [KEY_SYSRQ] = "SysRq",                  [KEY_RIGHTALT] = "RightAlt",
-       [KEY_LINEFEED] = "LineFeed",            [KEY_HOME] = "Home",
-       [KEY_UP] = "Up",                        [KEY_PAGEUP] = "PageUp",
-       [KEY_LEFT] = "Left",                    [KEY_RIGHT] = "Right",
-       [KEY_END] = "End",                      [KEY_DOWN] = "Down",
-       [KEY_PAGEDOWN] = "PageDown",            [KEY_INSERT] = "Insert",
-       [KEY_DELETE] = "Delete",                [KEY_MACRO] = "Macro",
-       [KEY_MUTE] = "Mute",                    [KEY_VOLUMEDOWN] = "VolumeDown",
-       [KEY_VOLUMEUP] = "VolumeUp",            [KEY_POWER] = "Power",
-       [KEY_KPEQUAL] = "KPEqual",              [KEY_KPPLUSMINUS] = "KPPlusMinus",
-       [KEY_PAUSE] = "Pause",                  [KEY_KPCOMMA] = "KPComma",
-       [KEY_HANGUEL] = "Hangeul",              [KEY_HANJA] = "Hanja",
-       [KEY_YEN] = "Yen",                      [KEY_LEFTMETA] = "LeftMeta",
-       [KEY_RIGHTMETA] = "RightMeta",          [KEY_COMPOSE] = "Compose",
-       [KEY_STOP] = "Stop",                    [KEY_AGAIN] = "Again",
-       [KEY_PROPS] = "Props",                  [KEY_UNDO] = "Undo",
-       [KEY_FRONT] = "Front",                  [KEY_COPY] = "Copy",
-       [KEY_OPEN] = "Open",                    [KEY_PASTE] = "Paste",
-       [KEY_FIND] = "Find",                    [KEY_CUT] = "Cut",
-       [KEY_HELP] = "Help",                    [KEY_MENU] = "Menu",
-       [KEY_CALC] = "Calc",                    [KEY_SETUP] = "Setup",
-       [KEY_SLEEP] = "Sleep",                  [KEY_WAKEUP] = "WakeUp",
-       [KEY_FILE] = "File",                    [KEY_SENDFILE] = "SendFile",
-       [KEY_DELETEFILE] = "DeleteFile",        [KEY_XFER] = "X-fer",
-       [KEY_PROG1] = "Prog1",                  [KEY_PROG2] = "Prog2",
-       [KEY_WWW] = "WWW",                      [KEY_MSDOS] = "MSDOS",
-       [KEY_COFFEE] = "Coffee",                [KEY_DIRECTION] = "Direction",
-       [KEY_CYCLEWINDOWS] = "CycleWindows",    [KEY_MAIL] = "Mail",
-       [KEY_BOOKMARKS] = "Bookmarks",          [KEY_COMPUTER] = "Computer",
-       [KEY_BACK] = "Back",                    [KEY_FORWARD] = "Forward",
-       [KEY_CLOSECD] = "CloseCD",              [KEY_EJECTCD] = "EjectCD",
-       [KEY_EJECTCLOSECD] = "EjectCloseCD",    [KEY_NEXTSONG] = "NextSong",
-       [KEY_PLAYPAUSE] = "PlayPause",          [KEY_PREVIOUSSONG] = "PreviousSong",
-       [KEY_STOPCD] = "StopCD",                [KEY_RECORD] = "Record",
-       [KEY_REWIND] = "Rewind",                [KEY_PHONE] = "Phone",
-       [KEY_ISO] = "ISOKey",                   [KEY_CONFIG] = "Config",
-       [KEY_HOMEPAGE] = "HomePage",            [KEY_REFRESH] = "Refresh",
-       [KEY_EXIT] = "Exit",                    [KEY_MOVE] = "Move",
-       [KEY_EDIT] = "Edit",                    [KEY_SCROLLUP] = "ScrollUp",
-       [KEY_SCROLLDOWN] = "ScrollDown",        [KEY_KPLEFTPAREN] = "KPLeftParenthesis",
-       [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New",
-       [KEY_REDO] = "Redo",                    [KEY_F13] = "F13",
-       [KEY_F14] = "F14",                      [KEY_F15] = "F15",
-       [KEY_F16] = "F16",                      [KEY_F17] = "F17",
-       [KEY_F18] = "F18",                      [KEY_F19] = "F19",
-       [KEY_F20] = "F20",                      [KEY_F21] = "F21",
-       [KEY_F22] = "F22",                      [KEY_F23] = "F23",
-       [KEY_F24] = "F24",                      [KEY_PLAYCD] = "PlayCD",
-       [KEY_PAUSECD] = "PauseCD",              [KEY_PROG3] = "Prog3",
-       [KEY_PROG4] = "Prog4",                  [KEY_SUSPEND] = "Suspend",
-       [KEY_CLOSE] = "Close",                  [KEY_PLAY] = "Play",
-       [KEY_FASTFORWARD] = "FastForward",      [KEY_BASSBOOST] = "BassBoost",
-       [KEY_PRINT] = "Print",                  [KEY_HP] = "HP",
-       [KEY_CAMERA] = "Camera",                [KEY_SOUND] = "Sound",
-       [KEY_QUESTION] = "Question",            [KEY_EMAIL] = "Email",
-       [KEY_CHAT] = "Chat",                    [KEY_SEARCH] = "Search",
-       [KEY_CONNECT] = "Connect",              [KEY_FINANCE] = "Finance",
-       [KEY_SPORT] = "Sport",                  [KEY_SHOP] = "Shop",
-       [KEY_ALTERASE] = "AlternateErase",      [KEY_CANCEL] = "Cancel",
-       [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp",
-       [KEY_MEDIA] = "Media",                  [KEY_UNKNOWN] = "Unknown",
-       [BTN_0] = "Btn0",                       [BTN_1] = "Btn1",
-       [BTN_2] = "Btn2",                       [BTN_3] = "Btn3",
-       [BTN_4] = "Btn4",                       [BTN_5] = "Btn5",
-       [BTN_6] = "Btn6",                       [BTN_7] = "Btn7",
-       [BTN_8] = "Btn8",                       [BTN_9] = "Btn9",
-       [BTN_LEFT] = "LeftBtn",                 [BTN_RIGHT] = "RightBtn",
-       [BTN_MIDDLE] = "MiddleBtn",             [BTN_SIDE] = "SideBtn",
-       [BTN_EXTRA] = "ExtraBtn",               [BTN_FORWARD] = "ForwardBtn",
-       [BTN_BACK] = "BackBtn",                 [BTN_TASK] = "TaskBtn",
-       [BTN_TRIGGER] = "Trigger",              [BTN_THUMB] = "ThumbBtn",
-       [BTN_THUMB2] = "ThumbBtn2",             [BTN_TOP] = "TopBtn",
-       [BTN_TOP2] = "TopBtn2",                 [BTN_PINKIE] = "PinkieBtn",
-       [BTN_BASE] = "BaseBtn",                 [BTN_BASE2] = "BaseBtn2",
-       [BTN_BASE3] = "BaseBtn3",               [BTN_BASE4] = "BaseBtn4",
-       [BTN_BASE5] = "BaseBtn5",               [BTN_BASE6] = "BaseBtn6",
-       [BTN_DEAD] = "BtnDead",                 [BTN_A] = "BtnA",
-       [BTN_B] = "BtnB",                       [BTN_C] = "BtnC",
-       [BTN_X] = "BtnX",                       [BTN_Y] = "BtnY",
-       [BTN_Z] = "BtnZ",                       [BTN_TL] = "BtnTL",
-       [BTN_TR] = "BtnTR",                     [BTN_TL2] = "BtnTL2",
-       [BTN_TR2] = "BtnTR2",                   [BTN_SELECT] = "BtnSelect",
-       [BTN_START] = "BtnStart",               [BTN_MODE] = "BtnMode",
-       [BTN_THUMBL] = "BtnThumbL",             [BTN_THUMBR] = "BtnThumbR",
-       [BTN_TOOL_PEN] = "ToolPen",             [BTN_TOOL_RUBBER] = "ToolRubber",
-       [BTN_TOOL_BRUSH] = "ToolBrush",         [BTN_TOOL_PENCIL] = "ToolPencil",
-       [BTN_TOOL_AIRBRUSH] = "ToolAirbrush",   [BTN_TOOL_FINGER] = "ToolFinger",
-       [BTN_TOOL_MOUSE] = "ToolMouse",         [BTN_TOOL_LENS] = "ToolLens",
-       [BTN_TOUCH] = "Touch",                  [BTN_STYLUS] = "Stylus",
-       [BTN_STYLUS2] = "Stylus2",              [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap",
-       [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn",
-       [BTN_GEAR_UP] = "Gear up",              [KEY_OK] = "Ok",
-       [KEY_SELECT] = "Select",                [KEY_GOTO] = "Goto",
-       [KEY_CLEAR] = "Clear",                  [KEY_POWER2] = "Power2",
-       [KEY_OPTION] = "Option",                [KEY_INFO] = "Info",
-       [KEY_TIME] = "Time",                    [KEY_VENDOR] = "Vendor",
-       [KEY_ARCHIVE] = "Archive",              [KEY_PROGRAM] = "Program",
-       [KEY_CHANNEL] = "Channel",              [KEY_FAVORITES] = "Favorites",
-       [KEY_EPG] = "EPG",                      [KEY_PVR] = "PVR",
-       [KEY_MHP] = "MHP",                      [KEY_LANGUAGE] = "Language",
-       [KEY_TITLE] = "Title",                  [KEY_SUBTITLE] = "Subtitle",
-       [KEY_ANGLE] = "Angle",                  [KEY_ZOOM] = "Zoom",
-       [KEY_MODE] = "Mode",                    [KEY_KEYBOARD] = "Keyboard",
-       [KEY_SCREEN] = "Screen",                [KEY_PC] = "PC",
-       [KEY_TV] = "TV",                        [KEY_TV2] = "TV2",
-       [KEY_VCR] = "VCR",                      [KEY_VCR2] = "VCR2",
-       [KEY_SAT] = "Sat",                      [KEY_SAT2] = "Sat2",
-       [KEY_CD] = "CD",                        [KEY_TAPE] = "Tape",
-       [KEY_RADIO] = "Radio",                  [KEY_TUNER] = "Tuner",
-       [KEY_PLAYER] = "Player",                [KEY_TEXT] = "Text",
-       [KEY_DVD] = "DVD",                      [KEY_AUX] = "Aux",
-       [KEY_MP3] = "MP3",                      [KEY_AUDIO] = "Audio",
-       [KEY_VIDEO] = "Video",                  [KEY_DIRECTORY] = "Directory",
-       [KEY_LIST] = "List",                    [KEY_MEMO] = "Memo",
-       [KEY_CALENDAR] = "Calendar",            [KEY_RED] = "Red",
-       [KEY_GREEN] = "Green",                  [KEY_YELLOW] = "Yellow",
-       [KEY_BLUE] = "Blue",                    [KEY_CHANNELUP] = "ChannelUp",
-       [KEY_CHANNELDOWN] = "ChannelDown",      [KEY_FIRST] = "First",
-       [KEY_LAST] = "Last",                    [KEY_AB] = "AB",
-       [KEY_NEXT] = "Next",                    [KEY_RESTART] = "Restart",
-       [KEY_SLOW] = "Slow",                    [KEY_SHUFFLE] = "Shuffle",
-       [KEY_BREAK] = "Break",                  [KEY_PREVIOUS] = "Previous",
-       [KEY_DIGITS] = "Digits",                [KEY_TEEN] = "TEEN",
-       [KEY_TWEN] = "TWEN",                    [KEY_DEL_EOL] = "DeleteEOL",
-       [KEY_DEL_EOS] = "DeleteEOS",            [KEY_INS_LINE] = "InsertLine",
-       [KEY_DEL_LINE] = "DeleteLine",
-       [KEY_SEND] = "Send",                    [KEY_REPLY] = "Reply",
-       [KEY_FORWARDMAIL] = "ForwardMail",      [KEY_SAVE] = "Save",
-       [KEY_DOCUMENTS] = "Documents",
-       [KEY_FN] = "Fn",                        [KEY_FN_ESC] = "Fn+ESC",
-       [KEY_FN_1] = "Fn+1",                    [KEY_FN_2] = "Fn+2",
-       [KEY_FN_B] = "Fn+B",                    [KEY_FN_D] = "Fn+D",
-       [KEY_FN_E] = "Fn+E",                    [KEY_FN_F] = "Fn+F",
-       [KEY_FN_S] = "Fn+S",
-       [KEY_FN_F1] = "Fn+F1",                  [KEY_FN_F2] = "Fn+F2",
-       [KEY_FN_F3] = "Fn+F3",                  [KEY_FN_F4] = "Fn+F4",
-       [KEY_FN_F5] = "Fn+F5",                  [KEY_FN_F6] = "Fn+F6",
-       [KEY_FN_F7] = "Fn+F7",                  [KEY_FN_F8] = "Fn+F8",
-       [KEY_FN_F9] = "Fn+F9",                  [KEY_FN_F10] = "Fn+F10",
-       [KEY_FN_F11] = "Fn+F11",                [KEY_FN_F12] = "Fn+F12",
-       [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle",
-       [KEY_KBDILLUMDOWN] = "KbdIlluminationDown",
-       [KEY_KBDILLUMUP] = "KbdIlluminationUp",
-       [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode",
-};
-
-static char *relatives[REL_MAX + 1] = {
-       [REL_X] = "X",                  [REL_Y] = "Y",
-       [REL_Z] = "Z",                  [REL_RX] = "Rx",
-       [REL_RY] = "Ry",                [REL_RZ] = "Rz",
-       [REL_HWHEEL] = "HWheel",        [REL_DIAL] = "Dial",
-       [REL_WHEEL] = "Wheel",          [REL_MISC] = "Misc",
-};
-
-static char *absolutes[ABS_MAX + 1] = {
-       [ABS_X] = "X",                  [ABS_Y] = "Y",
-       [ABS_Z] = "Z",                  [ABS_RX] = "Rx",
-       [ABS_RY] = "Ry",                [ABS_RZ] = "Rz",
-       [ABS_THROTTLE] = "Throttle",    [ABS_RUDDER] = "Rudder",
-       [ABS_WHEEL] = "Wheel",          [ABS_GAS] = "Gas",
-       [ABS_BRAKE] = "Brake",          [ABS_HAT0X] = "Hat0X",
-       [ABS_HAT0Y] = "Hat0Y",          [ABS_HAT1X] = "Hat1X",
-       [ABS_HAT1Y] = "Hat1Y",          [ABS_HAT2X] = "Hat2X",
-       [ABS_HAT2Y] = "Hat2Y",          [ABS_HAT3X] = "Hat3X",
-       [ABS_HAT3Y] = "Hat 3Y",         [ABS_PRESSURE] = "Pressure",
-       [ABS_DISTANCE] = "Distance",    [ABS_TILT_X] = "XTilt",
-       [ABS_TILT_Y] = "YTilt",         [ABS_TOOL_WIDTH] = "Tool Width",
-       [ABS_VOLUME] = "Volume",        [ABS_MISC] = "Misc",
-};
+#ifdef CONFIG_HID_DEBUG
 
-static char *misc[MSC_MAX + 1] = {
-       [MSC_SERIAL] = "Serial",        [MSC_PULSELED] = "Pulseled",
-       [MSC_GESTURE] = "Gesture",      [MSC_RAW] = "RawData"
-};
+void hid_dump_input(struct hid_usage *, __s32);
+void hid_dump_device(struct hid_device *);
+void hid_dump_field(struct hid_field *, int);
+void hid_resolv_usage(unsigned);
+void hid_resolv_event(__u8, __u16);
 
-static char *leds[LED_MAX + 1] = {
-       [LED_NUML] = "NumLock",         [LED_CAPSL] = "CapsLock",
-       [LED_SCROLLL] = "ScrollLock",   [LED_COMPOSE] = "Compose",
-       [LED_KANA] = "Kana",            [LED_SLEEP] = "Sleep",
-       [LED_SUSPEND] = "Suspend",      [LED_MUTE] = "Mute",
-       [LED_MISC] = "Misc",
-};
+#else
 
-static char *repeats[REP_MAX + 1] = {
-       [REP_DELAY] = "Delay",          [REP_PERIOD] = "Period"
-};
+#define hid_dump_input(a,b)     do { } while (0)
+#define hid_dump_device(c)      do { } while (0)
+#define hid_dump_field(a,b)     do { } while (0)
+#define hid_resolv_usage(a)         do { } while (0)
+#define hid_resolv_event(a,b)       do { } while (0)
 
-static char *sounds[SND_MAX + 1] = {
-       [SND_CLICK] = "Click",          [SND_BELL] = "Bell",
-       [SND_TONE] = "Tone"
-};
+#endif /* CONFIG_HID_DEBUG */
 
-static char **names[EV_MAX + 1] = {
-       [EV_SYN] = syncs,                       [EV_KEY] = keys,
-       [EV_REL] = relatives,                   [EV_ABS] = absolutes,
-       [EV_MSC] = misc,                        [EV_LED] = leds,
-       [EV_SND] = sounds,                      [EV_REP] = repeats,
-};
 
-static void __attribute__((unused)) resolv_event(__u8 type, __u16 code) {
+#endif
 
-       printk("%s.%s", events[type] ? events[type] : "?",
-               names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
-}
index 342b4e639acb7a1014e375186345d303458114a5..93173fe4563461e4b7f0df57451eb89c56e60004 100644 (file)
@@ -264,6 +264,8 @@ struct hid_item {
 #define HID_QUIRK_INVERT_HWHEEL                        0x00004000
 #define HID_QUIRK_POWERBOOK_ISO_KEYBOARD        0x00008000
 #define HID_QUIRK_BAD_RELATIVE_KEYS            0x00010000
+#define HID_QUIRK_SKIP_OUTPUT_REPORTS          0x00020000
+#define HID_QUIRK_IGNORE_MOUSE                 0x00040000
 
 /*
  * This is the global environment of the parser. This information is
@@ -430,8 +432,8 @@ struct hid_device {                                                 /* device report descriptor */
 
        /* device-specific function pointers */
        int (*hidinput_input_event) (struct input_dev *, unsigned int, unsigned int, int);
-       int (*hidinput_open) (struct input_dev *);
-       void (*hidinput_close) (struct input_dev *);
+       int (*hid_open) (struct hid_device *);
+       void (*hid_close) (struct hid_device *);
 
        /* hiddev event handler */
        void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field,
@@ -471,16 +473,6 @@ struct hid_descriptor {
        struct hid_class_descriptor desc[1];
 } __attribute__ ((packed));
 
-#ifdef DEBUG
-#include "hid-debug.h"
-#else
-#define hid_dump_input(a,b)    do { } while (0)
-#define hid_dump_device(c)     do { } while (0)
-#define hid_dump_field(a,b)    do { } while (0)
-#define resolv_usage(a)                do { } while (0)
-#define resolv_event(a,b)      do { } while (0)
-#endif
-
 /* Applications from HID Usage Tables 4/8/99 Version 1.1 */
 /* We ignore a few input applications that are not widely used */
 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001))
@@ -503,6 +495,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size);
 int hid_ff_init(struct hid_device *hid);
 
 int hid_lgff_init(struct hid_device *hid);
+int hid_plff_init(struct hid_device *hid);
 int hid_tmff_init(struct hid_device *hid);
 int hid_zpff_init(struct hid_device *hid);
 #ifdef CONFIG_HID_PID
index d0e6a5497614f7ead6dcb62ac5e9167cb591785d..e45712acfac57901bab5e5d0e5708586300eb91d 100644 (file)
@@ -71,6 +71,7 @@ struct mmc_card {
 #define MMC_STATE_SDCARD       (1<<3)          /* is an SD card */
 #define MMC_STATE_READONLY     (1<<4)          /* card is read-only */
 #define MMC_STATE_HIGHSPEED    (1<<5)          /* card is in high speed mode */
+#define MMC_STATE_BLOCKADDR    (1<<6)          /* card uses block-addressing */
        u32                     raw_cid[4];     /* raw card CID */
        u32                     raw_csd[4];     /* raw card CSD */
        u32                     raw_scr[2];     /* raw card SCR */
@@ -87,6 +88,7 @@ struct mmc_card {
 #define mmc_card_sd(c)         ((c)->state & MMC_STATE_SDCARD)
 #define mmc_card_readonly(c)   ((c)->state & MMC_STATE_READONLY)
 #define mmc_card_highspeed(c)  ((c)->state & MMC_STATE_HIGHSPEED)
+#define mmc_card_blockaddr(c)  ((c)->state & MMC_STATE_BLOCKADDR)
 
 #define mmc_card_set_present(c)        ((c)->state |= MMC_STATE_PRESENT)
 #define mmc_card_set_dead(c)   ((c)->state |= MMC_STATE_DEAD)
@@ -94,6 +96,7 @@ struct mmc_card {
 #define mmc_card_set_sd(c)     ((c)->state |= MMC_STATE_SDCARD)
 #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
 #define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED)
+#define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
 
 #define mmc_card_name(c)       ((c)->cid.prod_name)
 #define mmc_card_id(c)         ((c)->dev.bus_id)
index c15ae1986b9833e9727a3833be875e3daac93030..913e5752569f1c70f7c3cb6315af0d3514a22c92 100644 (file)
@@ -92,8 +92,10 @@ struct mmc_host {
        unsigned int            max_seg_size;   /* see blk_queue_max_segment_size */
        unsigned short          max_hw_segs;    /* see blk_queue_max_hw_segments */
        unsigned short          max_phys_segs;  /* see blk_queue_max_phys_segments */
-       unsigned short          max_sectors;    /* see blk_queue_max_sectors */
        unsigned short          unused;
+       unsigned int            max_req_size;   /* maximum number of bytes in one req */
+       unsigned int            max_blk_size;   /* maximum size of one mmc block */
+       unsigned int            max_blk_count;  /* maximum number of blocks in one req */
 
        /* private data */
        struct mmc_ios          ios;            /* current io bus settings */
@@ -106,8 +108,9 @@ struct mmc_host {
        struct list_head        cards;          /* devices attached to this host */
 
        wait_queue_head_t       wq;
-       spinlock_t              lock;           /* card_busy lock */
-       struct mmc_card         *card_busy;     /* the MMC card claiming host */
+       spinlock_t              lock;           /* claimed lock */
+       unsigned int            claimed:1;      /* host exclusively claimed */
+
        struct mmc_card         *card_selected; /* the selected MMC card */
 
        struct delayed_work     detect;
@@ -126,6 +129,7 @@ static inline void *mmc_priv(struct mmc_host *host)
 }
 
 #define mmc_dev(x)     ((x)->parent)
+#define mmc_classdev(x)        (&(x)->class_dev)
 #define mmc_hostname(x)        ((x)->class_dev.bus_id)
 
 extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
index bcf24909d67730ca79f416b4bfa0b2875939fdd5..cdc54be804f1b554e28ea85203651e783e7de905 100644 (file)
@@ -43,6 +43,7 @@ struct mmc_command {
 #define MMC_RSP_R2     (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC)
 #define MMC_RSP_R3     (MMC_RSP_PRESENT)
 #define MMC_RSP_R6     (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
+#define MMC_RSP_R7     (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
 
 #define mmc_resp_type(cmd)     ((cmd)->flags & (MMC_RSP_PRESENT|MMC_RSP_136|MMC_RSP_CRC|MMC_RSP_BUSY|MMC_RSP_OPCODE))
 
index 2dce60c43f4b2892538fe7d27fed55fa23db796e..c90b6768329d51b024de636c5c8c56ba721ff3ec 100644 (file)
 #define MMC_GEN_CMD              56   /* adtc [0] RD/WR          R1  */
 
 /* SD commands                           type  argument     response */
-  /* class 8 */
+  /* class 0 */
 /* This is basically the same command as for MMC with some quirks. */
 #define SD_SEND_RELATIVE_ADDR     3   /* bcr                     R6  */
+#define SD_SEND_IF_COND           8   /* bcr  [11:0] See below   R7  */
+
+  /* class 10 */
 #define SD_SWITCH                 6   /* adtc [31:0] See below   R1  */
 
   /* Application commands */
  *      [3:0] Function group 1
  */
 
+/*
+ * SD_SEND_IF_COND argument format:
+ *
+ *     [31:12] Reserved (0)
+ *     [11:8] Host Voltage Supply Flags
+ *     [7:0] Check Pattern (0xAA)
+ */
+
 /*
   MMC status in R1
   Type
index 3d1d21035dec23ecfd981cfd07acb9bf07e1f16e..ccd706f876ec118112e3591a6aa2d28ecb3893e8 100644 (file)
 #define PCI_DEVICE_ID_TI_TVP4020       0x3d07
 #define PCI_DEVICE_ID_TI_4450          0x8011
 #define PCI_DEVICE_ID_TI_XX21_XX11     0x8031
+#define PCI_DEVICE_ID_TI_XX21_XX11_FM  0x8033
 #define PCI_DEVICE_ID_TI_XX21_XX11_SD  0x8034
 #define PCI_DEVICE_ID_TI_X515          0x8036
 #define PCI_DEVICE_ID_TI_XX12          0x8039
+#define PCI_DEVICE_ID_TI_XX12_FM       0x803b
 #define PCI_DEVICE_ID_TI_1130          0xac12
 #define PCI_DEVICE_ID_TI_1031          0xac13
 #define PCI_DEVICE_ID_TI_1131          0xac15
 #define PCI_DEVICE_ID_TI_1510          0xac56
 #define PCI_DEVICE_ID_TI_X620          0xac8d
 #define PCI_DEVICE_ID_TI_X420          0xac8e
+#define PCI_DEVICE_ID_TI_XX20_FM       0xac8f
 
 #define PCI_VENDOR_ID_SONY             0x104d
 
 #define PCI_DEVICE_ID_TOPIC_TP560      0x0000
 
 #define PCI_VENDOR_ID_ENE              0x1524
+#define PCI_DEVICE_ID_ENE_CB712_SD     0x0550
 #define PCI_DEVICE_ID_ENE_1211         0x1211
 #define PCI_DEVICE_ID_ENE_1225         0x1225
 #define PCI_DEVICE_ID_ENE_1410         0x1410
index dfb8052eee5eb730938ae32a70ed579aed37cf86..3deb0a6c13708b7e6158dc52583982185a7c7003 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/wait.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
-#include <linux/scatterlist.h>
+#include <linux/kthread.h>
 
 /* Host registers (relative to pci base address): */
 enum {
@@ -62,11 +62,10 @@ enum {
 
 
 #define TIFM_IRQ_ENABLE           0x80000000
-#define TIFM_IRQ_SOCKMASK         0x00000001
-#define TIFM_IRQ_CARDMASK         0x00000100
-#define TIFM_IRQ_FIFOMASK         0x00010000
+#define TIFM_IRQ_SOCKMASK(x)      (x)
+#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
+#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
 #define TIFM_IRQ_SETALL           0xffffffff
-#define TIFM_IRQ_SETALLSOCK       0x0000000f
 
 #define TIFM_CTRL_LED             0x00000040
 #define TIFM_CTRL_FAST_CLK        0x00000100
@@ -89,10 +88,9 @@ struct tifm_dev {
        char __iomem            *addr;
        spinlock_t              lock;
        tifm_media_id           media_id;
-       char                    wq_name[KOBJ_NAME_LEN];
-       struct workqueue_struct *wq;
+       unsigned int            socket_id;
 
-       unsigned int            (*signal_irq)(struct tifm_dev *sock,
+       void                    (*signal_irq)(struct tifm_dev *sock,
                                              unsigned int sock_irq_status);
 
        struct tifm_driver      *drv;
@@ -103,24 +101,23 @@ struct tifm_driver {
        tifm_media_id        *id_table;
        int                  (*probe)(struct tifm_dev *dev);
        void                 (*remove)(struct tifm_dev *dev);
+       int                  (*suspend)(struct tifm_dev *dev,
+                                        pm_message_t state);
+       int                  (*resume)(struct tifm_dev *dev);
 
        struct device_driver driver;
 };
 
 struct tifm_adapter {
        char __iomem            *addr;
-       unsigned int            irq_status;
-       unsigned int            insert_mask;
-       unsigned int            remove_mask;
        spinlock_t              lock;
+       unsigned int            irq_status;
+       unsigned int            socket_change_set;
+       wait_queue_head_t       change_set_notify;
        unsigned int            id;
-       unsigned int            max_sockets;
-       char                    wq_name[KOBJ_NAME_LEN];
-       unsigned int            inhibit_new_cards;
-       struct workqueue_struct *wq;
-       struct work_struct      media_inserter;
-       struct work_struct      media_remover;
+       unsigned int            num_sockets;
        struct tifm_dev         **sockets;
+       struct task_struct      *media_switcher;
        struct class_device     cdev;
        struct device           *dev;
 
@@ -130,9 +127,9 @@ struct tifm_adapter {
 struct tifm_adapter *tifm_alloc_adapter(void);
 void tifm_free_device(struct device *dev);
 void tifm_free_adapter(struct tifm_adapter *fm);
-int tifm_add_adapter(struct tifm_adapter *fm);
+int tifm_add_adapter(struct tifm_adapter *fm, int (*mediathreadfn)(void *data));
 void tifm_remove_adapter(struct tifm_adapter *fm);
-struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id);
+struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm);
 int tifm_register_driver(struct tifm_driver *drv);
 void tifm_unregister_driver(struct tifm_driver *drv);
 void tifm_eject(struct tifm_dev *sock);
index 44537aa32e62319072c104058dfe020682576894..d66b15ea82c4ffaaa92540ee6a0a2b5747e66598 100644 (file)
@@ -98,7 +98,7 @@ struct ib_user_mad_hdr {
  */
 struct ib_user_mad {
        struct ib_user_mad_hdr hdr;
-       __u   data[0];
+       __u64   data[0];
 };
 
 /**
index 0bfa3328d686ccdac7cd383e8abac4063a90e5f6..765589f4d166f8d24fd1f7874c6169d296c97603 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/device.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <linux/kref.h>
 
 #include <asm/atomic.h>
 #include <asm/scatterlist.h>
@@ -419,8 +420,8 @@ struct ib_wc {
        enum ib_wc_opcode       opcode;
        u32                     vendor_err;
        u32                     byte_len;
+       struct ib_qp           *qp;
        __be32                  imm_data;
-       u32                     qp_num;
        u32                     src_qp;
        int                     wc_flags;
        u16                     pkey_index;
index 10625785eefd90d412668fce760190b122569bb9..50a43801018259422345f815b39876b6a1a6a78f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Dynamic DMA mapping support.
  *
- * This implementation is for IA-64 and EM64T platforms that do not support
+ * This implementation is a fallback for platforms that do not support
  * I/O TLBs (aka DMA address translation hardware).
  * Copyright (C) 2000 Asit Mallick <Asit.K.Mallick@intel.com>
  * Copyright (C) 2000 Goutham Rao <goutham.rao@intel.com>
@@ -28,6 +28,7 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/scatterlist.h>
+#include <asm/swiotlb.h>
 
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #define OFFSET(val,align) ((unsigned long)     \
                           ( (val) & ( (align) - 1)))
 
+#ifndef SG_ENT_VIRT_ADDRESS
 #define SG_ENT_VIRT_ADDRESS(sg)        (page_address((sg)->page) + (sg)->offset)
-#define SG_ENT_PHYS_ADDRESS(SG)        virt_to_phys(SG_ENT_VIRT_ADDRESS(SG))
+#define SG_ENT_PHYS_ADDRESS(sg)        virt_to_bus(SG_ENT_VIRT_ADDRESS(sg))
+#endif
 
 /*
  * Maximum allowable number of contiguous slabs to map,
@@ -101,13 +104,25 @@ static unsigned int io_tlb_index;
  * We need to save away the original address corresponding to a mapped entry
  * for the sync operations.
  */
-static unsigned char **io_tlb_orig_addr;
+#ifndef SWIOTLB_ARCH_HAS_IO_TLB_ADDR_T
+typedef char *io_tlb_addr_t;
+#define swiotlb_orig_addr_null(buffer) (!(buffer))
+#define ptr_to_io_tlb_addr(ptr) (ptr)
+#define page_to_io_tlb_addr(pg, off) (page_address(pg) + (off))
+#define sg_to_io_tlb_addr(sg) SG_ENT_VIRT_ADDRESS(sg)
+#endif
+static io_tlb_addr_t *io_tlb_orig_addr;
 
 /*
  * Protect the above data structures in the map and unmap calls
  */
 static DEFINE_SPINLOCK(io_tlb_lock);
 
+#ifdef SWIOTLB_EXTRA_VARIABLES
+SWIOTLB_EXTRA_VARIABLES;
+#endif
+
+#ifndef SWIOTLB_ARCH_HAS_SETUP_IO_TLB_NPAGES
 static int __init
 setup_io_tlb_npages(char *str)
 {
@@ -122,30 +137,50 @@ setup_io_tlb_npages(char *str)
                swiotlb_force = 1;
        return 1;
 }
+#endif
 __setup("swiotlb=", setup_io_tlb_npages);
 /* make io_tlb_overflow tunable too? */
 
+#ifndef swiotlb_adjust_size
+#define swiotlb_adjust_size(size) ((void)0)
+#endif
+
+#ifndef swiotlb_adjust_seg
+#define swiotlb_adjust_seg(start, size) ((void)0)
+#endif
+
+#ifndef swiotlb_print_info
+#define swiotlb_print_info(bytes) \
+       printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - " \
+              "0x%lx\n", bytes >> 20, \
+              virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end))
+#endif
+
 /*
  * Statically reserve bounce buffer space and initialize bounce buffer data
  * structures for the software IO TLB used to implement the DMA API.
  */
-void
-swiotlb_init_with_default_size (size_t default_size)
+void __init
+swiotlb_init_with_default_size(size_t default_size)
 {
-       unsigned long i;
+       unsigned long i, bytes;
 
        if (!io_tlb_nslabs) {
                io_tlb_nslabs = (default_size >> IO_TLB_SHIFT);
                io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
        }
+       swiotlb_adjust_size(io_tlb_nslabs);
+       swiotlb_adjust_size(io_tlb_overflow);
+
+       bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 
        /*
         * 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(bytes);
        if (!io_tlb_start)
                panic("Cannot allocate SWIOTLB buffer");
-       io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
+       io_tlb_end = io_tlb_start + bytes;
 
        /*
         * Allocate and initialize the free list array.  This array is used
@@ -153,34 +188,45 @@ swiotlb_init_with_default_size (size_t default_size)
         * between io_tlb_start and io_tlb_end.
         */
        io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int));
-       for (i = 0; i < io_tlb_nslabs; i++)
+       for (i = 0; i < io_tlb_nslabs; i++) {
+               if ( !(i % IO_TLB_SEGSIZE) )
+                       swiotlb_adjust_seg(io_tlb_start + (i << IO_TLB_SHIFT),
+                               IO_TLB_SEGSIZE << IO_TLB_SHIFT);
                io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
+       }
        io_tlb_index = 0;
-       io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
+       io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(io_tlb_addr_t));
 
        /*
         * Get the overflow emergency buffer
         */
        io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
-       printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n",
-              virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
+       if (!io_tlb_overflow_buffer)
+               panic("Cannot allocate SWIOTLB overflow buffer!\n");
+       swiotlb_adjust_seg(io_tlb_overflow_buffer, io_tlb_overflow);
+
+       swiotlb_print_info(bytes);
 }
+#ifndef __swiotlb_init_with_default_size
+#define __swiotlb_init_with_default_size swiotlb_init_with_default_size
+#endif
 
-void
-swiotlb_init (void)
+void __init
+swiotlb_init(void)
 {
-       swiotlb_init_with_default_size(64 * (1<<20));   /* default to 64MB */
+       __swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */
 }
 
+#ifdef SWIOTLB_ARCH_NEED_LATE_INIT
 /*
  * Systems with larger DMA zones (those that don't support ISA) can
  * initialize the swiotlb later using the slab allocator if needed.
  * This should be just like above, but with some error catching.
  */
 int
-swiotlb_late_init_with_default_size (size_t default_size)
+swiotlb_late_init_with_default_size(size_t default_size)
 {
-       unsigned long i, req_nslabs = io_tlb_nslabs;
+       unsigned long i, bytes, req_nslabs = io_tlb_nslabs;
        unsigned int order;
 
        if (!io_tlb_nslabs) {
@@ -191,8 +237,9 @@ swiotlb_late_init_with_default_size (size_t default_size)
        /*
         * Get IO TLB memory from the low pages
         */
-       order = get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
+       order = get_order(io_tlb_nslabs << IO_TLB_SHIFT);
        io_tlb_nslabs = SLABS_PER_PAGE << order;
+       bytes = io_tlb_nslabs << IO_TLB_SHIFT;
 
        while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
                io_tlb_start = (char *)__get_free_pages(GFP_DMA | __GFP_NOWARN,
@@ -205,13 +252,14 @@ swiotlb_late_init_with_default_size (size_t default_size)
        if (!io_tlb_start)
                goto cleanup1;
 
-       if (order != get_order(io_tlb_nslabs * (1 << IO_TLB_SHIFT))) {
+       if (order != get_order(bytes)) {
                printk(KERN_WARNING "Warning: only able to allocate %ld MB "
                       "for software IO TLB\n", (PAGE_SIZE << order) >> 20);
                io_tlb_nslabs = SLABS_PER_PAGE << order;
+               bytes = io_tlb_nslabs << IO_TLB_SHIFT;
        }
-       io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
-       memset(io_tlb_start, 0, io_tlb_nslabs * (1 << IO_TLB_SHIFT));
+       io_tlb_end = io_tlb_start + bytes;
+       memset(io_tlb_start, 0, bytes);
 
        /*
         * Allocate and initialize the free list array.  This array is used
@@ -227,12 +275,12 @@ swiotlb_late_init_with_default_size (size_t default_size)
                io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
        io_tlb_index = 0;
 
-       io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL,
-                                  get_order(io_tlb_nslabs * sizeof(char *)));
+       io_tlb_orig_addr = (io_tlb_addr_t *)__get_free_pages(GFP_KERNEL,
+                                  get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t)));
        if (!io_tlb_orig_addr)
                goto cleanup3;
 
-       memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *));
+       memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(io_tlb_addr_t));
 
        /*
         * Get the overflow emergency buffer
@@ -242,29 +290,29 @@ swiotlb_late_init_with_default_size (size_t default_size)
        if (!io_tlb_overflow_buffer)
                goto cleanup4;
 
-       printk(KERN_INFO "Placing %ldMB software IO TLB between 0x%lx - "
-              "0x%lx\n", (io_tlb_nslabs * (1 << IO_TLB_SHIFT)) >> 20,
-              virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
+       swiotlb_print_info(bytes);
 
        return 0;
 
 cleanup4:
-       free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs *
-                                                             sizeof(char *)));
+       free_pages((unsigned long)io_tlb_orig_addr,
+                  get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t)));
        io_tlb_orig_addr = NULL;
 cleanup3:
-       free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
-                                                        sizeof(int)));
+       free_pages((unsigned long)io_tlb_list,
+                  get_order(io_tlb_nslabs * sizeof(int)));
        io_tlb_list = NULL;
-       io_tlb_end = NULL;
 cleanup2:
+       io_tlb_end = NULL;
        free_pages((unsigned long)io_tlb_start, order);
        io_tlb_start = NULL;
 cleanup1:
        io_tlb_nslabs = req_nslabs;
        return -ENOMEM;
 }
+#endif
 
+#ifndef SWIOTLB_ARCH_HAS_NEEDS_MAPPING
 static inline int
 address_needs_mapping(struct device *hwdev, dma_addr_t addr)
 {
@@ -275,11 +323,35 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr)
        return (addr & ~mask) != 0;
 }
 
+static inline int range_needs_mapping(const void *ptr, size_t size)
+{
+       return swiotlb_force;
+}
+
+static inline int order_needs_mapping(unsigned int order)
+{
+       return 0;
+}
+#endif
+
+static void
+__sync_single(io_tlb_addr_t buffer, char *dma_addr, size_t size, int dir)
+{
+#ifndef SWIOTLB_ARCH_HAS_SYNC_SINGLE
+       if (dir == DMA_TO_DEVICE)
+               memcpy(dma_addr, buffer, size);
+       else
+               memcpy(buffer, dma_addr, size);
+#else
+       __swiotlb_arch_sync_single(buffer, dma_addr, size, dir);
+#endif
+}
+
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
 static void *
-map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+map_single(struct device *hwdev, io_tlb_addr_t buffer, size_t size, int dir)
 {
        unsigned long flags;
        char *dma_addr;
@@ -352,7 +424,7 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
         */
        io_tlb_orig_addr[index] = buffer;
        if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
-               memcpy(dma_addr, buffer, size);
+               __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
 
        return dma_addr;
 }
@@ -366,17 +438,18 @@ unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
        unsigned long flags;
        int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
        int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-       char *buffer = io_tlb_orig_addr[index];
+       io_tlb_addr_t buffer = io_tlb_orig_addr[index];
 
        /*
         * First, sync the memory before unmapping the entry
         */
-       if (buffer && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
+       if (!swiotlb_orig_addr_null(buffer)
+           && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
                /*
                 * bounce... copy the data back into the original buffer * and
                 * delete the bounce buffer.
                 */
-               memcpy(buffer, dma_addr, size);
+               __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
 
        /*
         * Return the buffer to the free list by setting the corresponding
@@ -409,18 +482,18 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
            int dir, int target)
 {
        int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT;
-       char *buffer = io_tlb_orig_addr[index];
+       io_tlb_addr_t buffer = io_tlb_orig_addr[index];
 
        switch (target) {
        case SYNC_FOR_CPU:
                if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
-                       memcpy(buffer, dma_addr, size);
+                       __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
                else
                        BUG_ON(dir != DMA_TO_DEVICE);
                break;
        case SYNC_FOR_DEVICE:
                if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
-                       memcpy(dma_addr, buffer, size);
+                       __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
                else
                        BUG_ON(dir != DMA_FROM_DEVICE);
                break;
@@ -429,11 +502,13 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size,
        }
 }
 
+#ifdef SWIOTLB_ARCH_NEED_ALLOC
+
 void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                       dma_addr_t *dma_handle, gfp_t flags)
 {
-       unsigned long dev_addr;
+       dma_addr_t dev_addr;
        void *ret;
        int order = get_order(size);
 
@@ -444,8 +519,11 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
         */
        flags |= GFP_DMA;
 
-       ret = (void *)__get_free_pages(flags, order);
-       if (ret && address_needs_mapping(hwdev, virt_to_phys(ret))) {
+       if (!order_needs_mapping(order))
+               ret = (void *)__get_free_pages(flags, order);
+       else
+               ret = NULL;
+       if (ret && address_needs_mapping(hwdev, virt_to_bus(ret))) {
                /*
                 * The allocated memory isn't reachable by the device.
                 * Fall back on swiotlb_map_single().
@@ -465,22 +543,24 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                if (swiotlb_dma_mapping_error(handle))
                        return NULL;
 
-               ret = phys_to_virt(handle);
+               ret = bus_to_virt(handle);
        }
 
        memset(ret, 0, size);
-       dev_addr = virt_to_phys(ret);
+       dev_addr = virt_to_bus(ret);
 
        /* Confirm address can be DMA'd by device */
        if (address_needs_mapping(hwdev, dev_addr)) {
-               printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016lx\n",
-                      (unsigned long long)*hwdev->dma_mask, dev_addr);
+               printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
+                      (unsigned long long)*hwdev->dma_mask,
+                      (unsigned long long)dev_addr);
                panic("swiotlb_alloc_coherent: allocated memory is out of "
                      "range for device");
        }
        *dma_handle = dev_addr;
        return ret;
 }
+EXPORT_SYMBOL(swiotlb_alloc_coherent);
 
 void
 swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
@@ -493,6 +573,9 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
                /* DMA_TO_DEVICE to avoid memcpy in unmap_single */
                swiotlb_unmap_single (hwdev, dma_handle, size, DMA_TO_DEVICE);
 }
+EXPORT_SYMBOL(swiotlb_free_coherent);
+
+#endif
 
 static void
 swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
@@ -504,7 +587,7 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
         * When the mapping is small enough return a static buffer to limit
         * the damage, or panic when the transfer is too big.
         */
-       printk(KERN_ERR "DMA: Out of SW-IOMMU space for %lu bytes at "
+       printk(KERN_ERR "DMA: Out of SW-IOMMU space for %zu bytes at "
               "device %s\n", size, dev ? dev->bus_id : "?");
 
        if (size > io_tlb_overflow && do_panic) {
@@ -525,7 +608,7 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
 dma_addr_t
 swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
 {
-       unsigned long dev_addr = virt_to_phys(ptr);
+       dma_addr_t dev_addr = virt_to_bus(ptr);
        void *map;
 
        BUG_ON(dir == DMA_NONE);
@@ -534,19 +617,20 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
         * we can safely return the device addr and not worry about bounce
         * buffering it.
         */
-       if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force)
+       if (!range_needs_mapping(ptr, size)
+           && !address_needs_mapping(hwdev, dev_addr))
                return dev_addr;
 
        /*
         * Oh well, have to allocate and map a bounce buffer.
         */
-       map = map_single(hwdev, ptr, size, dir);
+       map = map_single(hwdev, ptr_to_io_tlb_addr(ptr), size, dir);
        if (!map) {
                swiotlb_full(hwdev, size, dir, 1);
                map = io_tlb_overflow_buffer;
        }
 
-       dev_addr = virt_to_phys(map);
+       dev_addr = virt_to_bus(map);
 
        /*
         * Ensure that the address returned is DMA'ble
@@ -557,25 +641,6 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir)
        return dev_addr;
 }
 
-/*
- * Since DMA is i-cache coherent, any (complete) pages that were written via
- * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
- * flush them when they get mapped into an executable vm-area.
- */
-static void
-mark_clean(void *addr, size_t size)
-{
-       unsigned long pg_addr, end;
-
-       pg_addr = PAGE_ALIGN((unsigned long) addr);
-       end = (unsigned long) addr + size;
-       while (pg_addr + PAGE_SIZE <= end) {
-               struct page *page = virt_to_page(pg_addr);
-               set_bit(PG_arch_1, &page->flags);
-               pg_addr += PAGE_SIZE;
-       }
-}
-
 /*
  * Unmap a single streaming mode DMA translation.  The dma_addr and size must
  * match what was provided for in a previous swiotlb_map_single call.  All
@@ -588,13 +653,13 @@ void
 swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, size_t size,
                     int dir)
 {
-       char *dma_addr = phys_to_virt(dev_addr);
+       char *dma_addr = bus_to_virt(dev_addr);
 
        BUG_ON(dir == DMA_NONE);
        if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
                unmap_single(hwdev, dma_addr, size, dir);
        else if (dir == DMA_FROM_DEVICE)
-               mark_clean(dma_addr, size);
+               dma_mark_clean(dma_addr, size);
 }
 
 /*
@@ -611,13 +676,13 @@ static inline void
 swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
                    size_t size, int dir, int target)
 {
-       char *dma_addr = phys_to_virt(dev_addr);
+       char *dma_addr = bus_to_virt(dev_addr);
 
        BUG_ON(dir == DMA_NONE);
        if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
                sync_single(hwdev, dma_addr, size, dir, target);
        else if (dir == DMA_FROM_DEVICE)
-               mark_clean(dma_addr, size);
+               dma_mark_clean(dma_addr, size);
 }
 
 void
@@ -642,13 +707,13 @@ swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr,
                          unsigned long offset, size_t size,
                          int dir, int target)
 {
-       char *dma_addr = phys_to_virt(dev_addr) + offset;
+       char *dma_addr = bus_to_virt(dev_addr) + offset;
 
        BUG_ON(dir == DMA_NONE);
        if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
                sync_single(hwdev, dma_addr, size, dir, target);
        else if (dir == DMA_FROM_DEVICE)
-               mark_clean(dma_addr, size);
+               dma_mark_clean(dma_addr, size);
 }
 
 void
@@ -687,18 +752,16 @@ int
 swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
               int dir)
 {
-       void *addr;
-       unsigned long dev_addr;
+       dma_addr_t dev_addr;
        int i;
 
        BUG_ON(dir == DMA_NONE);
 
        for (i = 0; i < nelems; i++, sg++) {
-               addr = SG_ENT_VIRT_ADDRESS(sg);
-               dev_addr = virt_to_phys(addr);
-               if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
-                       void *map = map_single(hwdev, addr, sg->length, dir);
-                       sg->dma_address = virt_to_bus(map);
+               dev_addr = SG_ENT_PHYS_ADDRESS(sg);
+               if (range_needs_mapping(SG_ENT_VIRT_ADDRESS(sg), sg->length)
+                   || address_needs_mapping(hwdev, dev_addr)) {
+                       void *map = map_single(hwdev, sg_to_io_tlb_addr(sg), sg->length, dir);
                        if (!map) {
                                /* Don't panic here, we expect map_sg users
                                   to do proper error handling. */
@@ -707,6 +770,7 @@ swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
                                sg[0].dma_length = 0;
                                return 0;
                        }
+                       sg->dma_address = virt_to_bus(map);
                } else
                        sg->dma_address = dev_addr;
                sg->dma_length = sg->length;
@@ -728,9 +792,10 @@ swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nelems,
 
        for (i = 0; i < nelems; i++, sg++)
                if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
-                       unmap_single(hwdev, (void *) phys_to_virt(sg->dma_address), sg->dma_length, dir);
+                       unmap_single(hwdev, bus_to_virt(sg->dma_address),
+                                    sg->dma_length, dir);
                else if (dir == DMA_FROM_DEVICE)
-                       mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
+                       dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 }
 
 /*
@@ -750,8 +815,10 @@ swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg,
 
        for (i = 0; i < nelems; i++, sg++)
                if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
-                       sync_single(hwdev, (void *) sg->dma_address,
+                       sync_single(hwdev, bus_to_virt(sg->dma_address),
                                    sg->dma_length, dir, target);
+               else if (dir == DMA_FROM_DEVICE)
+                       dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 }
 
 void
@@ -768,10 +835,48 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
        swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE);
 }
 
+#ifdef SWIOTLB_ARCH_NEED_MAP_PAGE
+
+dma_addr_t
+swiotlb_map_page(struct device *hwdev, struct page *page,
+                unsigned long offset, size_t size,
+                enum dma_data_direction direction)
+{
+       dma_addr_t dev_addr;
+       char *map;
+
+       dev_addr = page_to_bus(page) + offset;
+       if (address_needs_mapping(hwdev, dev_addr)) {
+               map = map_single(hwdev, page_to_io_tlb_addr(page, offset), size, direction);
+               if (!map) {
+                       swiotlb_full(hwdev, size, direction, 1);
+                       map = io_tlb_overflow_buffer;
+               }
+               dev_addr = virt_to_bus(map);
+       }
+
+       return dev_addr;
+}
+
+void
+swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
+                  size_t size, enum dma_data_direction direction)
+{
+       char *dma_addr = bus_to_virt(dev_addr);
+
+       BUG_ON(direction == DMA_NONE);
+       if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end)
+               unmap_single(hwdev, dma_addr, size, direction);
+       else if (direction == DMA_FROM_DEVICE)
+               dma_mark_clean(dma_addr, size);
+}
+
+#endif
+
 int
 swiotlb_dma_mapping_error(dma_addr_t dma_addr)
 {
-       return (dma_addr == virt_to_phys(io_tlb_overflow_buffer));
+       return (dma_addr == virt_to_bus(io_tlb_overflow_buffer));
 }
 
 /*
@@ -780,10 +885,13 @@ swiotlb_dma_mapping_error(dma_addr_t dma_addr)
  * during bus mastering, then you would pass 0x00ffffff as the mask to
  * this function.
  */
+#ifndef __swiotlb_dma_supported
+#define __swiotlb_dma_supported(hwdev, mask) (virt_to_bus(io_tlb_end - 1) <= (mask))
+#endif
 int
-swiotlb_dma_supported (struct device *hwdev, u64 mask)
+swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
-       return (virt_to_phys (io_tlb_end) - 1) <= mask;
+       return __swiotlb_dma_supported(hwdev, mask);
 }
 
 EXPORT_SYMBOL(swiotlb_init);
@@ -798,6 +906,4 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device);
 EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
 EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 EXPORT_SYMBOL(swiotlb_dma_mapping_error);
-EXPORT_SYMBOL(swiotlb_alloc_coherent);
-EXPORT_SYMBOL(swiotlb_free_coherent);
 EXPORT_SYMBOL(swiotlb_dma_supported);
index f01f8c072852b5b7b1871d9955170346b55a0e5a..96926eb13b0a5f59edd14849e32c825143c2eb18 100644 (file)
@@ -1,7 +1,7 @@
 ####
 # kbuild: Generic definitions
 
-# Convinient variables
+# Convenient constants
 comma   := ,
 squote  := '
 empty   :=
@@ -56,40 +56,46 @@ endef
 # gcc support functions
 # See documentation in Documentation/kbuild/makefiles.txt
 
-# output directory for tests below
-TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
+# checker-shell
+# Usage: option = $(call checker-shell, $(CC)...-o $$OUT, option-ok, otherwise)
+# Exit code chooses option. $$OUT is safe location for needless output.
+define checker-shell
+  $(shell set -e; \
+    DIR=$(KBUILD_EXTMOD); \
+    cd $${DIR:-$(objtree)}; \
+    OUT=$$PWD/.$$$$.null; \
+    \
+    ln -s /dev/null $$OUT; \
+    if $(1) >/dev/null 2>&1; \
+      then echo "$(2)"; \
+      else echo "$(3)"; \
+    fi; \
+    rm -f $$OUT)
+endef
 
 # as-option
 # Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
-
-as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
-            -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
-            else echo "$(2)"; fi ;)
+as-option = $(call checker-shell, \
+   $(CC) $(CFLAGS) $(1) -c -xassembler /dev/null -o $$OUT, $(1), $(2))
 
 # as-instr
 # Usage: cflags-y += $(call as-instr, instr, option1, option2)
-
-as-instr = $(shell if echo -e "$(1)" | \
-                     $(CC) $(AFLAGS) -c -xassembler - \
-                           -o $(TMPOUT)astest$$$$.out > /dev/null 2>&1; \
-                  then rm $(TMPOUT)astest$$$$.out; echo "$(2)"; \
-                  else echo "$(3)"; fi)
+as-instr = $(call checker-shell, \
+   printf "$(1)" | $(CC) $(AFLAGS) -c -xassembler -o $$OUT -, $(2), $(3))
 
 # cc-option
 # Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
-
-cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
-             > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+cc-option = $(call checker-shell, \
+   $(CC) $(CFLAGS) $(if $(3),$(3),$(1)) -S -xc /dev/null -o $$OUT, $(1), $(2))
 
 # cc-option-yn
 # Usage: flag := $(call cc-option-yn, -march=winchip-c6)
-cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
-                > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
+cc-option-yn = $(call cc-option, "y", "n", $(1))
 
 # cc-option-align
 # Prefix align with either -falign or -malign
 cc-option-align = $(subst -functions=0,,\
-       $(call cc-option,-falign-functions=0,-malign-functions=0))
+   $(call cc-option,-falign-functions=0,-malign-functions=0))
 
 # cc-version
 # Usage gcc-ver := $(call cc-version, $(CC))
@@ -97,35 +103,42 @@ cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
 
 # cc-ifversion
 # Usage:  EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
-cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
-                       echo $(3); fi;)
+cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
 
 # ld-option
 # Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both)
-ld-option = $(shell if $(CC) $(1) -nostdlib -xc /dev/null \
-                            -o $(TMPOUT)ldtest$$$$.out > /dev/null 2>&1; \
-             then rm $(TMPOUT)ldtest$$$$.out; echo "$(1)"; \
-             else echo "$(2)"; fi)
+ld-option = $(call checker-shell, \
+   $(CC) $(1) -nostdlib -xc /dev/null -o $$OUT, $(1), $(2))
+
+######
 
-###
 # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
 # Usage:
 # $(Q)$(MAKE) $(build)=dir
 build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
 
-# Prefix -I with $(srctree) if it is not an absolute path
-addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
+# Prefix -I with $(srctree) if it is not an absolute path,
+# add original to the end
+addtree = $(if \
+       $(filter-out -I/%, $(1)), $(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
+
 # Find all -I options and call addtree
-flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
+flags = $(foreach o,$($(1)), \
+       $(if $(filter -I%,$(o)), $(call addtree, $(o)), $(o)))
 
-# If quiet is set, only print short version of command
+# echo command.
+# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
+echo-cmd = $(if $($(quiet)cmd_$(1)), \
+       echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
+
+# printing commands
 cmd = @$(echo-cmd) $(cmd_$(1))
 
-# Add $(obj)/ for paths that is not absolute
-objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
+# Add $(obj)/ for paths that are not absolute
+objectify = $(foreach o,$(1), $(if $(filter /%,$(o)), $(o), $(obj)/$(o)))
 
 ###
-# if_changed      - execute command if any prerequisite is newer than 
+# if_changed      - execute command if any prerequisite is newer than
 #                   target, or command line has changed
 # if_changed_dep  - as if_changed, but uses fixdep to reveal dependencies
 #                   including used config symbols
@@ -133,16 +146,12 @@ objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
 # See Documentation/kbuild/makefiles.txt for more info
 
 ifneq ($(KBUILD_NOCMDDEP),1)
-# Check if both arguments has same arguments. Result in empty string if equal
+# Check if both arguments has same arguments. Result is empty string, if equal.
 # User may override this check using make KBUILD_NOCMDDEP=1
 arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
                     $(filter-out $(cmd_$@),   $(cmd_$(1))) )
 endif
 
-# echo command. Short version is $(quiet) equals quiet, otherwise full command
-echo-cmd = $(if $($(quiet)cmd_$(1)), \
-       echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
-
 # >'< substitution is for echo to work,
 # >$< substitution to preserve $ when reloading .cmd file
 # note: when using inline perl scripts [perl -e '...$$t=1;...']
@@ -153,15 +162,15 @@ make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
 # PHONY targets skipped in both cases.
 any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
 
-# Execute command if command has changed or prerequisitei(s) are updated
+# Execute command if command has changed or prerequisite(s) are updated.
 #
 if_changed = $(if $(strip $(any-prereq) $(arg-check)),                       \
        @set -e;                                                             \
        $(echo-cmd) $(cmd_$(1));                                             \
        echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
 
-# execute the command and also postprocess generated .d dependencies
-# file
+# Execute the command and also postprocess generated .d dependencies file.
+#
 if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ),                  \
        @set -e;                                                             \
        $(echo-cmd) $(cmd_$(1));                                             \
@@ -169,9 +178,10 @@ if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ),                  \
        rm -f $(depfile);                                                    \
        mv -f $(dot-target).tmp $(dot-target).cmd)
 
+# Will check if $(cmd_foo) changed, or any of the prerequisites changed,
+# and if so will execute $(rule_foo).
 # Usage: $(call if_changed_rule,foo)
-# will check if $(cmd_foo) changed, or any of the prequisites changed,
-# and if so will execute $(rule_foo)
+#
 if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ),                 \
        @set -e;                                                             \
        $(rule_$(1)))
index 4c723fd18648daba8926e8b73e727b45c90fc1d9..43f75d6e4d9629a963806d6b4108d2dbd7164d01 100644 (file)
@@ -1,6 +1,6 @@
 #!/bin/bash
 # Copyright (C) Martin Schlemmer <azarah@nosferatu.za.org>
-# Copyright (c) 2006           Sam Ravnborg <sam@ravnborg.org>
+# Copyright (C) 2006 Sam Ravnborg <sam@ravnborg.org>
 #
 # Released under the terms of the GNU GPL
 #
@@ -17,15 +17,15 @@ cat << EOF
 Usage:
 $0 [-o <file>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...
        -o <file>      Create gzipped initramfs file named <file> using
-                      gen_init_cpio and gzip
+                      gen_init_cpio and gzip
        -u <uid>       User ID to map to user ID 0 (root).
-                      <uid> is only meaningful if <cpio_source>
-                      is a directory.
+                      <uid> is only meaningful if <cpio_source>
+                      is a directory.
        -g <gid>       Group ID to map to group ID 0 (root).
-                      <gid> is only meaningful if <cpio_source>
-                      is a directory.
+                      <gid> is only meaningful if <cpio_source>
+                      is a directory.
        <cpio_source>  File list or directory for cpio archive.
-                      If <cpio_source> is a .cpio file it will be used
+                      If <cpio_source> is a .cpio file it will be used
                       as direct input to initramfs.
        -d             Output the default cpio list.
 
@@ -36,6 +36,12 @@ to reset the root/group mapping.
 EOF
 }
 
+# awk style field access
+# $1 - field number; rest is argument string
+field() {
+       shift $1 ; echo $1
+}
+
 list_default_initramfs() {
        # echo usr/kinit/kinit
        :
@@ -119,22 +125,17 @@ parse() {
                        str="${ftype} ${name} ${location} ${str}"
                        ;;
                "nod")
-                       local dev_type=
-                       local maj=$(LC_ALL=C ls -l "${location}" | \
-                                       gawk '{sub(/,/, "", $5); print $5}')
-                       local min=$(LC_ALL=C ls -l "${location}" | \
-                                       gawk '{print $6}')
-
-                       if [ -b "${location}" ]; then
-                               dev_type="b"
-                       else
-                               dev_type="c"
-                       fi
-                       str="${ftype} ${name} ${str} ${dev_type} ${maj} ${min}"
+                       local dev=`LC_ALL=C ls -l "${location}"`
+                       local maj=`field 5 ${dev}`
+                       local min=`field 6 ${dev}`
+                       maj=${maj%,}
+
+                       [ -b "${location}" ] && dev="b" || dev="c"
+
+                       str="${ftype} ${name} ${str} ${dev} ${maj} ${min}"
                        ;;
                "slink")
-                       local target=$(LC_ALL=C ls -l "${location}" | \
-                                       gawk '{print $11}')
+                       local target=`field 11 $(LC_ALL=C ls -l "${location}")`
                        str="${ftype} ${name} ${target} ${str}"
                        ;;
                *)
index 34bd72391238d5c6d04ed9d7a9e031d82d8175a0..4fc80f2b7e19d7c814e91e25309c181ba7649bc1 100755 (executable)
@@ -1,31 +1,31 @@
-#!/bin/bash
+#!/bin/sh
 # A script to dump mixed source code & assembly
 # with correct relocations from System.map
-# Requires the following lines in Rules.make.
-# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 
-#            William Stearns <wstearns@pobox.com>
+# Requires the following lines in makefile:
 #%.lst: %.c
 #      $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $<
-#      $(TOPDIR)/scripts/makelst $*.o $(TOPDIR)/System.map $(OBJDUMP)
+#      $(srctree)/scripts/makelst $*.o $(objtree)/System.map $(OBJDUMP)
 #
-#    Copyright (C) 2000 IBM Corporation
-#    Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 
+# Copyright (C) 2000 IBM Corporation
+# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+#            William Stearns <wstearns@pobox.com>
 #
 
-t1=`$3 --syms $1 | grep .text | grep " F " | head -n 1`
+# awk style field access
+field() {
+  shift $1 ; echo $1
+}
+
+t1=`$3 --syms $1 | grep .text | grep -m1 " F "`
 if [ -n "$t1" ]; then
-  t2=`echo $t1 | gawk '{ print $6 }'`
+  t2=`field 6 $t1`
   if [ ! -r $2 ]; then
     echo "No System.map" >&2
-    t7=0
   else
     t3=`grep $t2 $2`
-    t4=`echo $t3 | gawk '{ print $1 }'`
-    t5=`echo $t1 | gawk '{ print $1 }'`
-    t6=`echo $t4 - $t5 | tr a-f A-F`
-    t7=`( echo  ibase=16 ; echo $t6 ) | bc`
+    t4=`field 1 $t3`
+    t5=`field 1 $t1`
+    t6=`printf "%lu" $((0x$t4 - 0x$t5))`
   fi
-else
-  t7=0
 fi
-$3 -r --source --adjust-vma=$t7 $1
+$3 -r --source --adjust-vma=${t6:-0} $1
index ac9326c5f1da3f1e1781d8654ac816bb83355560..700400d801dcc1e5360427bfc07c9c722a256c46 100644 (file)
@@ -188,6 +188,7 @@ static inline void key_alloc_serial(struct key *key)
 
        spin_lock(&key_serial_lock);
 
+attempt_insertion:
        parent = NULL;
        p = &key_serial_tree.rb_node;
 
@@ -202,39 +203,33 @@ static inline void key_alloc_serial(struct key *key)
                else
                        goto serial_exists;
        }
-       goto insert_here;
+
+       /* we've found a suitable hole - arrange for this key to occupy it */
+       rb_link_node(&key->serial_node, parent, p);
+       rb_insert_color(&key->serial_node, &key_serial_tree);
+
+       spin_unlock(&key_serial_lock);
+       return;
 
        /* we found a key with the proposed serial number - walk the tree from
         * that point looking for the next unused serial number */
 serial_exists:
        for (;;) {
                key->serial++;
-               if (key->serial < 2)
-                       key->serial = 2;
-
-               if (!rb_parent(parent))
-                       p = &key_serial_tree.rb_node;
-               else if (rb_parent(parent)->rb_left == parent)
-                       p = &(rb_parent(parent)->rb_left);
-               else
-                       p = &(rb_parent(parent)->rb_right);
+               if (key->serial < 3) {
+                       key->serial = 3;
+                       goto attempt_insertion;
+               }
 
                parent = rb_next(parent);
                if (!parent)
-                       break;
+                       goto attempt_insertion;
 
                xkey = rb_entry(parent, struct key, serial_node);
                if (key->serial < xkey->serial)
-                       goto insert_here;
+                       goto attempt_insertion;
        }
 
-       /* we've found a suitable hole - arrange for this key to occupy it */
-insert_here:
-       rb_link_node(&key->serial_node, parent, p);
-       rb_insert_color(&key->serial_node, &key_serial_tree);
-
-       spin_unlock(&key_serial_lock);
-
 } /* end key_alloc_serial() */
 
 /*****************************************************************************/