Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
authorSteve French <sfrench@us.ibm.com>
Wed, 7 Feb 2007 00:30:38 +0000 (00:30 +0000)
committerSteve French <sfrench@us.ibm.com>
Wed, 7 Feb 2007 00:30:38 +0000 (00:30 +0000)
448 files changed:
Documentation/s390/Debugging390.txt
Documentation/sysrq.txt
MAINTAINERS
Makefile
arch/i386/boot/compressed/relocs.c
arch/i386/kernel/cpu/cyrix.c
arch/i386/kernel/efi.c
arch/i386/mach-default/setup.c
arch/ia64/kernel/acpi.c
arch/ia64/kernel/irq.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-32/memset.S [deleted file]
arch/mips/lib-64/Makefile
arch/mips/lib-64/memset.S [deleted file]
arch/mips/lib/Makefile
arch/mips/lib/memset.S [new file with mode: 0644]
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/math-emu/sfp-util.h [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/sparc/kernel/smp.c
arch/sparc/kernel/sun4d_smp.c
crypto/Kconfig
drivers/ata/libata-core.c
drivers/ata/pata_atiixp.c
drivers/ata/pata_jmicron.c
drivers/ata/pata_via.c
drivers/char/sysrq.c
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/ide/ide.c
drivers/ide/pci/via82cxxx.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/kvm/vmx.c
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/net/bnx2.c
drivers/net/bnx2.h
drivers/net/e100.c
drivers/net/hamradio/Kconfig
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_ethtool.c
drivers/net/netxen/netxen_nic_hw.c
drivers/net/netxen/netxen_nic_hw.h
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_isr.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/netxen/netxen_nic_niu.c
drivers/net/smc911x.c
drivers/net/spider_net.c
drivers/pci/quirks.c
drivers/pci/search.c
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/scsi/qla4xxx/ql4_def.h
drivers/scsi/qla4xxx/ql4_glbl.h
drivers/scsi/qla4xxx/ql4_init.c
drivers/scsi/qla4xxx/ql4_isr.c
drivers/scsi/qla4xxx/ql4_mbx.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/qla4xxx/ql4_version.h
drivers/scsi/scsi_scan.c
drivers/scsi/sd.c
drivers/scsi/st.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]
drivers/usb/net/rtl8150.c
fs/aio.c
fs/block_dev.c
fs/nfsd/nfsfh.c
fs/ocfs2/journal.h
fs/proc/base.c
include/asm-alpha/unistd.h
include/asm-frv/Kbuild
include/asm-frv/page.h
include/asm-frv/ptrace.h
include/asm-frv/termios.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 [new file with mode: 0644]
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-sparc/checksum.h
include/asm-um/pgtable.h
include/asm-x86_64/dma-mapping.h
include/linux/efi.h
include/linux/hid-debug.h
include/linux/hid.h
include/linux/libata.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
kernel/fork.c
net/ipv4/netfilter/ip_conntrack_netlink.c
net/netfilter/Kconfig
net/netfilter/nf_conntrack_netlink.c
net/sched/act_ipt.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 e0188a23fd5e7183768362da2ae4c5c72eebd059..61613166981b9139a5961fe0c3344cbd03286688 100644 (file)
@@ -1,6 +1,6 @@
 Linux Magic System Request Key Hacks
-Documentation for sysrq.c version 1.15
-Last update: $Date: 2001/01/28 10:15:59 $
+Documentation for sysrq.c
+Last update: 2007-JAN-06
 
 *  What is the magic SysRq key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -35,7 +35,7 @@ You can set the value in the file by the following command:
 
 Note that the value of /proc/sys/kernel/sysrq influences only the invocation
 via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always
-allowed.
+allowed (by a user with admin privileges).
 
 *  How do I use the magic SysRq key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -58,7 +58,7 @@ On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>,
 On other - If you know of the key combos for other architectures, please
            let me know so I can add them to this section.
 
-On all -  write a character to /proc/sysrq-trigger.  eg:
+On all -  write a character to /proc/sysrq-trigger.  e.g.:
 
                echo t > /proc/sysrq-trigger
 
@@ -74,6 +74,8 @@ On all -  write a character to /proc/sysrq-trigger.  eg:
 
 'c'    - Will perform a kexec reboot in order to take a crashdump.
 
+'d'    - Shows all locks that are held.
+
 'o'     - Will shut your system off (if configured and supported).
 
 's'     - Will attempt to sync all mounted filesystems.
@@ -87,38 +89,43 @@ On all -  write a character to /proc/sysrq-trigger.  eg:
 
 'm'     - Will dump current memory info to your console.
 
+'n'    - Used to make RT tasks nice-able
+
 'v'    - Dumps Voyager SMP processor info to your console.
 
+'w'    - Dumps tasks that are in uninterruptable (blocked) state.
+
+'x'    - Used by xmon interface on ppc/powerpc platforms.
+
 '0'-'9' - Sets the console log level, controlling which kernel messages
           will be printed to your console. ('0', for example would make
           it so that only emergency messages like PANICs or OOPSes would
           make it to your console.)
 
-'f'    - Will call oom_kill to kill a memory hog process
+'f'    - Will call oom_kill to kill a memory hog process.
 
 'e'     - Send a SIGTERM to all processes, except for init.
 
-'i'     - Send a SIGKILL to all processes, except for init.
+'g'    - Used by kgdb on ppc platforms.
 
-'l'     - Send a SIGKILL to all processes, INCLUDING init. (Your system
-          will be non-functional after this.)
+'i'     - Send a SIGKILL to all processes, except for init.
 
-'h'     - Will display help ( actually any other key than those listed
+'h'     - Will display help (actually any other key than those listed
           above will display help. but 'h' is easy to remember :-)
 
 *  Okay, so what can I use them for?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Well, un'R'aw is very handy when your X server or a svgalib program crashes.
 
-sa'K' (Secure Access Key) is useful when you want to be sure there are no
-trojan program is running at console and which could grab your password
-when you would try to login. It will kill all programs on given console
-and thus letting you make sure that the login prompt you see is actually
+sa'K' (Secure Access Key) is useful when you want to be sure there is no
+trojan program running at console which could grab your password
+when you would try to login. It will kill all programs on given console,
+thus letting you make sure that the login prompt you see is actually
 the one from init, not some trojan program.
 IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT
 IMPORTANT: c2 compliant system, and it should not be mistaken as   :IMPORTANT
 IMPORTANT: such.                                                   :IMPORTANT
-       It seems other find it useful as (System Attention Key) which is
+       It seems others find it useful as (System Attention Key) which is
 useful when you want to exit a program that will not let you switch consoles.
 (For example, X or a svgalib program.)
 
@@ -139,8 +146,8 @@ OK or Done message...)
 Again, the unmount (remount read-only) hasn't taken place until you see the
 "OK" and "Done" message appear on the screen.
 
-The loglevel'0'-'9' is useful when your console is being flooded with
-kernel messages you do not want to see. Setting '0' will prevent all but
+The loglevels '0'-'9' are useful when your console is being flooded with
+kernel messages you do not want to see. Selecting '0' will prevent all but
 the most urgent kernel messages from reaching your console. (They will
 still be logged if syslogd/klogd are alive, though.)
 
@@ -152,7 +159,7 @@ processes.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 That happens to me, also. I've found that tapping shift, alt, and control
 on both sides of the keyboard, and hitting an invalid sysrq sequence again
-will fix the problem. (ie, something like alt-sysrq-z). Switching to another
+will fix the problem. (i.e., something like alt-sysrq-z). Switching to another
 virtual console (ALT+Fn) and then back again should also help.
 
 *  I hit SysRq, but nothing seems to happen, what's wrong?
@@ -174,11 +181,11 @@ handler function you will use, B) a help_msg string, that will print when SysRQ
 prints help, and C) an action_msg string, that will print right before your
 handler is called. Your handler must conform to the prototype in 'sysrq.h'.
 
-After the sysrq_key_op is created, you can call the macro 
-register_sysrq_key(int key, struct sysrq_key_op *op_p) that is defined in
-sysrq.h, this will register the operation pointed to by 'op_p' at table
-key 'key', if that slot in the table is blank. At module unload time, you must
-call the macro unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
+After the sysrq_key_op is created, you can call the kernel function
+register_sysrq_key(int key, struct sysrq_key_op *op_p); this will
+register the operation pointed to by 'op_p' at table key 'key',
+if that slot in the table is blank. At module unload time, you must call
+the function unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
 will remove the key op pointed to by 'op_p' from the key 'key', if and only if
 it is currently registered in that slot. This is in case the slot has been
 overwritten since you registered it.
@@ -186,15 +193,12 @@ overwritten since you registered it.
 The Magic SysRQ system works by registering key operations against a key op
 lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has
 a number of operations registered into it at compile time, but is mutable,
-and 4 functions are exported for interface to it: __sysrq_lock_table,
-__sysrq_unlock_table, __sysrq_get_key_op, and __sysrq_put_key_op. The
-functions __sysrq_swap_key_ops and __sysrq_swap_key_ops_nolock are defined
-in the header itself, and the REGISTER and UNREGISTER macros are built from
-these. More complex (and dangerous!) manipulations of the table are possible
-using these functions, but you must be careful to always lock the table before
-you read or write from it, and to unlock it again when you are done. (And of
-course, to never ever leave an invalid pointer in the table). Null pointers in
-the table are always safe :)
+and 2 functions are exported for interface to it:
+       register_sysrq_key and unregister_sysrq_key.
+Of course, never ever leave an invalid pointer in the table. I.e., when
+your module that called register_sysrq_key() exits, it must call
+unregister_sysrq_key() to clean up the sysrq key table entry that it used.
+Null pointers in the table are always safe. :)
 
 If for some reason you feel the need to call the handle_sysrq function from
 within a function called by handle_sysrq, you must be aware that you are in
index a275f72ed5f7abb2e9c47e4dd877214cd4d7282c..16c0e15b5785699b9563679140c98f5760dc03b8 100644 (file)
@@ -598,8 +598,6 @@ W:  http://linux-atm.sourceforge.net
 S:     Maintained
 
 ATMEL MACB ETHERNET DRIVER
-P:     Atmel AVR32 Support Team
-M:     avr32@atmel.com
 P:     Haavard Skinnemoen
 M:     hskinnemoen@atmel.com
 S:     Supported
@@ -620,8 +618,6 @@ T:  git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git
 S:     Maintained
 
 AVR32 ARCHITECTURE
-P:     Atmel AVR32 Support Team
-M:     avr32@atmel.com
 P:     Haavard Skinnemoen
 M:     hskinnemoen@atmel.com
 W:     http://www.atmel.com/products/AVR32/
@@ -630,8 +626,6 @@ W:  http://avrfreaks.net/
 S:     Supported
 
 AVR32/AT32AP MACHINE SUPPORT
-P:     Atmel AVR32 Support Team
-M:     avr32@atmel.com
 P:     Haavard Skinnemoen
 M:     hskinnemoen@atmel.com
 S:     Supported
@@ -2797,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
 
@@ -2805,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
 
@@ -2813,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
 
@@ -3599,6 +3593,12 @@ M:       ysato@users.sourceforge.jp
 W:     http://uclinux-h8.sourceforge.jp/
 S:     Supported
 
+UFS FILESYSTEM
+P: Evgeniy Dushistov
+M: dushistov@mail.ru
+L: linux-kernel@vger.kernel.org
+S: Maintained
+
 USB DIAMOND RIO500 DRIVER
 P:     Cesar Miquel
 M:     miquel@df.uba.ar
@@ -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 75adfb539977d42a35ee77913cbb102304b0f81f..cdeda68cf2aa9082571366837a504fe80ef6c40e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 20
-EXTRAVERSION =-rc7
+EXTRAVERSION =
 NAME = Homicidal Dwarf Hamster
 
 # *DOCUMENTATION*
@@ -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 468da89153c470ee2311a30ac445cabd2301755b..881951ca03e1cc53be63665b5c717e04adf1d47a 100644 (file)
@@ -43,6 +43,8 @@ static int is_safe_abs_reloc(const char* sym_name)
                        /* Match found */
                        return 1;
        }
+       if (strncmp(sym_name, "__crc_", 6) == 0)
+               return 1;
        return 0;
 }
 
index abcff92f994c06eafd9aa52f13b1401498c789fa..c0c3b59de32c4d183b677e843ffacffa5aa2f1bb 100644 (file)
@@ -173,7 +173,7 @@ static void __cpuinit geode_configure(void)
        ccr4 = getCx86(CX86_CCR4);
        ccr4 |= 0x38;           /* FPU fast, DTE cache, Mem bypass */
        
-       setCx86(CX86_CCR4, ccr4);
+       setCx86(CX86_CCR3, ccr3);
        
        set_cx86_memwb();
        set_cx86_reorder();     
index b92c7f0a358aa79836a2ccbc56cd7bf386555a80..8f9c624ace6fb46d2094485b8c8c051f6f7d72ee 100644 (file)
@@ -472,6 +472,70 @@ static inline void __init check_range_for_systab(efi_memory_desc_t *md)
        }
 }
 
+/*
+ * Wrap all the virtual calls in a way that forces the parameters on the stack.
+ */
+
+#define efi_call_virt(f, args...) \
+     ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args)
+
+static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+       return efi_call_virt(get_time, tm, tc);
+}
+
+static efi_status_t virt_efi_set_time (efi_time_t *tm)
+{
+       return efi_call_virt(set_time, tm);
+}
+
+static efi_status_t virt_efi_get_wakeup_time (efi_bool_t *enabled,
+                                             efi_bool_t *pending,
+                                             efi_time_t *tm)
+{
+       return efi_call_virt(get_wakeup_time, enabled, pending, tm);
+}
+
+static efi_status_t virt_efi_set_wakeup_time (efi_bool_t enabled,
+                                             efi_time_t *tm)
+{
+       return efi_call_virt(set_wakeup_time, enabled, tm);
+}
+
+static efi_status_t virt_efi_get_variable (efi_char16_t *name,
+                                          efi_guid_t *vendor, u32 *attr,
+                                          unsigned long *data_size, void *data)
+{
+       return efi_call_virt(get_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_get_next_variable (unsigned long *name_size,
+                                               efi_char16_t *name,
+                                               efi_guid_t *vendor)
+{
+       return efi_call_virt(get_next_variable, name_size, name, vendor);
+}
+
+static efi_status_t virt_efi_set_variable (efi_char16_t *name,
+                                          efi_guid_t *vendor,
+                                          unsigned long attr,
+                                          unsigned long data_size, void *data)
+{
+       return efi_call_virt(set_variable, name, vendor, attr, data_size, data);
+}
+
+static efi_status_t virt_efi_get_next_high_mono_count (u32 *count)
+{
+       return efi_call_virt(get_next_high_mono_count, count);
+}
+
+static void virt_efi_reset_system (int reset_type, efi_status_t status,
+                                  unsigned long data_size,
+                                  efi_char16_t *data)
+{
+       efi_call_virt(reset_system, reset_type, status, data_size, data);
+}
+
 /*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
@@ -525,22 +589,15 @@ void __init efi_enter_virtual_mode(void)
         * pointers in the runtime service table to the new virtual addresses.
         */
 
-       efi.get_time = (efi_get_time_t *) efi.systab->runtime->get_time;
-       efi.set_time = (efi_set_time_t *) efi.systab->runtime->set_time;
-       efi.get_wakeup_time = (efi_get_wakeup_time_t *)
-                                       efi.systab->runtime->get_wakeup_time;
-       efi.set_wakeup_time = (efi_set_wakeup_time_t *)
-                                       efi.systab->runtime->set_wakeup_time;
-       efi.get_variable = (efi_get_variable_t *)
-                                       efi.systab->runtime->get_variable;
-       efi.get_next_variable = (efi_get_next_variable_t *)
-                                       efi.systab->runtime->get_next_variable;
-       efi.set_variable = (efi_set_variable_t *)
-                                       efi.systab->runtime->set_variable;
-       efi.get_next_high_mono_count = (efi_get_next_high_mono_count_t *)
-                                       efi.systab->runtime->get_next_high_mono_count;
-       efi.reset_system = (efi_reset_system_t *)
-                                       efi.systab->runtime->reset_system;
+       efi.get_time = virt_efi_get_time;
+       efi.set_time = virt_efi_set_time;
+       efi.get_wakeup_time = virt_efi_get_wakeup_time;
+       efi.set_wakeup_time = virt_efi_set_wakeup_time;
+       efi.get_variable = virt_efi_get_variable;
+       efi.get_next_variable = virt_efi_get_next_variable;
+       efi.set_variable = virt_efi_set_variable;
+       efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
+       efi.reset_system = virt_efi_reset_system;
 }
 
 void __init
index c511705c386cc6b251b6c3707864b356155a04bd..cc2f519b2f7f6c41a5b6ff5fdbe082fa730b5734 100644 (file)
@@ -102,7 +102,7 @@ void __init time_init_hook(void)
  *     along the MCA bus.  Use this to hook into that chain if you will need
  *     it.
  **/
-void __init mca_nmi_hook(void)
+void mca_nmi_hook(void)
 {
        /* If I recall correctly, there's a whole bunch of other things that
         * we can do to check for NMI problems, but that's all I know about
index ef2fe474f107319c90af67317de180162d22ed2b..29f05d4b68cdd7f17911f8b840838faa795be2c4 100644 (file)
@@ -609,6 +609,9 @@ EXPORT_SYMBOL(acpi_register_gsi);
 
 void acpi_unregister_gsi(u32 gsi)
 {
+       if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
+               return;
+
        iosapic_unregister_intr(gsi);
 }
 
index 54d55e4d64f7e1e70aa30d8d2c853a35bafe5f0a..ce49c85c928f5fe44f52501c86211b11926c89d8 100644 (file)
@@ -122,6 +122,9 @@ static void migrate_irqs(void)
        for (irq=0; irq < NR_IRQS; irq++) {
                desc = irq_desc + irq;
 
+               if (desc->status == IRQ_DISABLED)
+                       continue;
+
                /*
                 * No handling for now.
                 * TBD: Implement a disable function so we can now
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
diff --git a/arch/mips/lib-32/memset.S b/arch/mips/lib-32/memset.S
deleted file mode 100644 (file)
index 1981485..0000000
+++ /dev/null
@@ -1,145 +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)
-       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)
-       EX(LONG_S, \val, (\offset + 11 * LONGSIZE)(\dst), \fixup)
-       EX(LONG_S, \val, (\offset + 12 * LONGSIZE)(\dst), \fixup)
-       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)
-       .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 */
-       sll             t1, a1, 8
-       or              a1, t1
-       sll             t1, a1, 16
-       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(swl, a1, (a0), first_fixup)          /* make word aligned */
-#endif
-#ifdef __MIPSEL__
-       EX(swr, a1, (a0), first_fixup)          /* make word 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, 0x3c
-
-       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 */
-       PTR_SUBU        t1, t0
-       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(swr, a1, -1(a0), last_fixup)
-#endif
-#ifdef __MIPSEL__
-       EX(swl, 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 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
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
new file mode 100644 (file)
index 0000000..3f8b8b3
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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>
+
+#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";                        \
+       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)
+#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)
+       EX(LONG_S, \val, (\offset + 11 * LONGSIZE)(\dst), \fixup)
+       EX(LONG_S, \val, (\offset + 12 * LONGSIZE)(\dst), \fixup)
+       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
+
+/*
+ * 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 */
+       LONG_SLL                t1, a1, 8
+       or              a1, t1
+       LONG_SLL                t1, a1, 16
+#if LONGSIZE == 8
+       or              a1, t1
+       LONG_SLL                t1, a1, 32
+#endif
+       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(LONG_S_L, a1, (a0), first_fixup)     /* make word/dword aligned */
+#endif
+#ifdef __MIPSEL__
+       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 */
+
+1:     ori             t1, a2, 0x3f            /* # of full blocks */
+       xori            t1, 0x3f
+       beqz            t1, memset_partial      /* no block to fill */
+        andi           t0, a2, 0x40-LONGSIZE
+
+       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 */
+#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 */
+
+       .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(LONG_S_R, a1, -1(a0), last_fixup)
+#endif
+#ifdef __MIPSEL__
+       EX(LONG_S_L, 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 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
diff --git a/arch/s390/math-emu/sfp-util.h b/arch/s390/math-emu/sfp-util.h
deleted file mode 100644 (file)
index 5b6ca45..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) ({          \
-       unsigned int __sh = (ah);                       \
-       unsigned int __sl = (al);                       \
-       asm volatile(                                   \
-               "       alr     %1,%3\n"                \
-               "       brc     12,0f\n"                \
-               "       ahi     %0,1\n"                 \
-               "0:     alr  %0,%2"                     \
-               : "+&d" (__sh), "+d" (__sl)             \
-               : "d" (bh), "d" (bl) : "cc");           \
-       (sh) = __sh;                                    \
-       (sl) = __sl;                                    \
-})
-
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) ({          \
-       unsigned int __sh = (ah);                       \
-       unsigned int __sl = (al);                       \
-       asm volatile(                                   \
-               "       slr     %1,%3\n"                \
-               "       brc     3,0f\n"                 \
-               "       ahi     %0,-1\n"                \
-               "0:     slr     %0,%2"                  \
-               : "+&d" (__sh), "+d" (__sl)             \
-               : "d" (bh), "d" (bl) : "cc");           \
-       (sh) = __sh;                                    \
-       (sl) = __sl;                                    \
-})
-
-/* a umul b = a mul b + (a>=2<<31) ? b<<32:0 + (b>=2<<31) ? a<<32:0 */
-#define umul_ppmm(wh, wl, u, v) ({                     \
-       unsigned int __wh = u;                          \
-       unsigned int __wl = v;                          \
-       asm volatile(                                   \
-               "       ltr     1,%0\n"                 \
-               "       mr      0,%1\n"                 \
-               "       jnm     0f\n"                           \
-               "       alr     0,%1\n"                 \
-               "0:     ltr     %1,%1\n"                        \
-               "       jnm     1f\n"                           \
-               "       alr     0,%0\n"                 \
-               "1:     lr      %0,0\n"                 \
-               "       lr      %1,1\n"                 \
-               : "+d" (__wh), "+d" (__wl)              \
-               : : "0", "1", "cc");                    \
-       wh = __wh;                                      \
-       wl = __wl;                                      \
-})
-
-#define udiv_qrnnd(q, r, n1, n0, d)                    \
-  do { unsigned long __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);
-
-#define UDIV_NEEDS_NORMALIZATION 0
-
-#define abort() return 0
-
-#define __BYTE_ORDER __BIG_ENDIAN
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 276f22881d0fd764cd3922037eed8f962138d646..6b5f26b0fb75c5e716574a70122a79b675b62708 100644 (file)
@@ -292,8 +292,8 @@ int setup_profiling_timer(unsigned int multiplier)
 
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-       extern void smp4m_boot_cpus(void);
-       extern void smp4d_boot_cpus(void);
+       extern void __init smp4m_boot_cpus(void);
+       extern void __init smp4d_boot_cpus(void);
        int i, cpuid, extra;
 
        printk("Entering SMP Mode...\n");
@@ -375,8 +375,8 @@ void __init smp_prepare_boot_cpu(void)
 
 int __cpuinit __cpu_up(unsigned int cpu)
 {
-       extern int smp4m_boot_one_cpu(int);
-       extern int smp4d_boot_one_cpu(int);
+       extern int __cpuinit smp4m_boot_one_cpu(int);
+       extern int __cpuinit smp4d_boot_one_cpu(int);
        int ret=0;
 
        switch(sparc_cpu_model) {
index c80ea61e8ba0e84d8ca1c00fc9df0668477759d2..c69de5d4863d69cff95df5cc1a16d21441dc83a0 100644 (file)
@@ -164,7 +164,7 @@ void __init smp4d_boot_cpus(void)
        local_flush_cache_all();
 }
 
-int smp4d_boot_one_cpu(int i)
+int __cpuinit smp4d_boot_one_cpu(int i)
 {
                        extern unsigned long sun4d_cpu_startup;
                        unsigned long *entry = &sun4d_cpu_startup;
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 cf707029352e29ac034a118518b1632cc303c0c5..667acd283364503c328fd4dcd7c1dbadc2ac5d85 100644 (file)
@@ -1250,6 +1250,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
 
                ata_sg_init(qc, sg, n_elem);
                qc->nsect = buflen / ATA_SECT_SIZE;
+               qc->nbytes = buflen;
        }
 
        qc->private_data = &wait;
index 6f6672c551319a09ef998ca88889e5ba4998fe45..504e1dbfffd7d9d6581fe4432c8e266bcd70730e 100644 (file)
@@ -36,15 +36,22 @@ enum {
 static int atiixp_pre_reset(struct ata_port *ap)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-       static struct pci_bits atiixp_enable_bits[] = {
+       static const struct pci_bits atiixp_enable_bits[] = {
                { 0x48, 1, 0x01, 0x00 },
                { 0x48, 1, 0x08, 0x00 }
        };
+       u8 udma;
 
        if (!pci_test_config_bits(pdev, &atiixp_enable_bits[ap->port_no]))
                return -ENOENT;
 
-       ap->cbl = ATA_CBL_PATA80;
+       /* Hack from drivers/ide/pci. Really we want to know how to do the
+          raw detection not play follow the bios mode guess */
+       pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ap->port_no, &udma);
+       if ((udma & 0x07) >= 0x04 || (udma & 0x70) >= 0x40)
+               ap->cbl = ATA_CBL_PATA80;
+       else
+               ap->cbl = ATA_CBL_PATA40;
        return ata_std_prereset(ap);
 }
 
index 2d661cb4df3cd75470af0e98f58e2bbb42886191..d50264af284811d164b231f4a4d01e352b8751d0 100644 (file)
@@ -204,20 +204,12 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
 
        u32 reg;
 
-       if (id->driver_data != 368) {
-               /* Put the controller into AHCI mode in case the AHCI driver
-                  has not yet been loaded. This can be done with either
-                  function present */
+       /* PATA controller is fn 1, AHCI is fn 0 */
+       if (id->driver_data != 368 && PCI_FUNC(pdev->devfn) != 1)
+               return -ENODEV;
 
-               /* FIXME: We may want a way to override this in future */
-               pci_write_config_byte(pdev, 0x41, 0xa1);
-
-               /* PATA controller is fn 1, AHCI is fn 0 */
-               if (PCI_FUNC(pdev->devfn) != 1)
-                       return -ENODEV;
-       }
-       if ( id->driver_data == 365 || id->driver_data == 366) {
-               /* The 365/66 have two PATA channels, redirect the second */
+       /* The 365/66 have two PATA channels, redirect the second */
+       if (id->driver_data == 365 || id->driver_data == 366) {
                pci_read_config_dword(pdev, 0x80, &reg);
                reg |= (1 << 24);       /* IDE1 to PATA IDE secondary */
                pci_write_config_dword(pdev, 0x80, reg);
index 0219419cae97878dfcbb56edfefcb10bd2519a00..f0b6c3b7142931a30cb3524a033fb021393a2c47 100644 (file)
@@ -23,6 +23,7 @@
  *     VIA VT8233c     -       UDMA100
  *     VIA VT8235      -       UDMA133
  *     VIA VT8237      -       UDMA133
+ *     VIA VT8237S     -       UDMA133
  *     VIA VT8251      -       UDMA133
  *
  *     Most registers remain compatible across chips. Others start reserved
@@ -61,7 +62,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_via"
-#define DRV_VERSION "0.2.0"
+#define DRV_VERSION "0.2.1"
 
 /*
  *     The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx
index 13935235e0661b1b82eb6be10e298b8c5a63b0f2..7fd3cd5ddf2190269e206383ece44c481a889f78 100644 (file)
@@ -215,7 +215,7 @@ static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty)
 }
 static struct sysrq_key_op sysrq_showstate_blocked_op = {
        .handler        = sysrq_handle_showstate_blocked,
-       .help_msg       = "showBlockedTasks",
+       .help_msg       = "shoW-blocked-tasks",
        .action_msg     = "Show Blocked State",
        .enable_mask    = SYSRQ_ENABLE_DUMP,
 };
@@ -315,15 +315,16 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
        &sysrq_loglevel_op,             /* 9 */
 
        /*
-        * Don't use for system provided sysrqs, it is handled specially on
-        * sparc and will never arrive
+        * a: Don't use for system provided sysrqs, it is handled specially on
+        * sparc and will never arrive.
         */
        NULL,                           /* a */
        &sysrq_reboot_op,               /* b */
-       &sysrq_crashdump_op,            /* c */
+       &sysrq_crashdump_op,            /* c & ibm_emac driver debug */
        &sysrq_showlocks_op,            /* d */
        &sysrq_term_op,                 /* e */
        &sysrq_moom_op,                 /* f */
+       /* g: May be registered by ppc for kgdb */
        NULL,                           /* g */
        NULL,                           /* h */
        &sysrq_kill_op,                 /* i */
@@ -332,18 +333,19 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
        NULL,                           /* l */
        &sysrq_showmem_op,              /* m */
        &sysrq_unrt_op,                 /* n */
-       /* This will often be registered as 'Off' at init time */
+       /* o: This will often be registered as 'Off' at init time */
        NULL,                           /* o */
        &sysrq_showregs_op,             /* p */
        NULL,                           /* q */
-       &sysrq_unraw_op,                        /* r */
+       &sysrq_unraw_op,                /* r */
        &sysrq_sync_op,                 /* s */
        &sysrq_showstate_op,            /* t */
        &sysrq_mountro_op,              /* u */
-       /* May be assigned at init time by SMP VOYAGER */
+       /* v: May be registered at init time by SMP VOYAGER */
        NULL,                           /* v */
-       NULL,                           /* w */
-       &sysrq_showstate_blocked_op,    /* x */
+       &sysrq_showstate_blocked_op,    /* w */
+       /* x: May be registered on ppc/powerpc for xmon */
+       NULL,                           /* x */
        NULL,                           /* y */
        NULL                            /* z */
 };
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 3b334af0c7b98d1cb39ae07ec5e714998f385102..6c9bd5165bdb53911792b08e4624d7aa94c5b93a 100644 (file)
@@ -1781,9 +1781,9 @@ done:
        return 1;
 }
 
-extern void pnpide_init(void);
-extern void pnpide_exit(void);
-extern void h8300_ide_init(void);
+extern void __init pnpide_init(void);
+extern void __exit pnpide_exit(void);
+extern void __init h8300_ide_init(void);
 
 /*
  * probe_for_hwifs() finds/initializes "known" IDE interfaces
@@ -2088,7 +2088,7 @@ int __init init_module (void)
        return ide_init();
 }
 
-void cleanup_module (void)
+void __exit cleanup_module (void)
 {
        int index;
 
index a98b4d38b9dd7678741262d8809236642d704c0a..6fb6e50b82312131b1b3ac45f29f927c0f6a7e07 100644 (file)
@@ -78,7 +78,7 @@ static struct via_isa_bridge {
        u8 rev_max;
        u16 flags;
 } via_isa_bridges[] = {
-       { "cx7000",     PCI_DEVICE_ID_VIA_CX700,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
+       { "cx700",      PCI_DEVICE_ID_VIA_CX700,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "vt8237s",    PCI_DEVICE_ID_VIA_8237S,    0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "vt6410",     PCI_DEVICE_ID_VIA_6410,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
        { "vt8251",     PCI_DEVICE_ID_VIA_8251,     0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
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 27f2751c3baa66e404631f37c5ddb7ed15ebc23f..54c35c0b31815670dd56cbc54b18826e1ea6f80d 100644 (file)
@@ -1116,6 +1116,8 @@ static int vmx_vcpu_setup(struct kvm_vcpu *vcpu)
 
                if (rdmsr_safe(index, &data_low, &data_high) < 0)
                        continue;
+               if (wrmsr_safe(index, data_low, data_high) < 0)
+                       continue;
                data = data_low | ((u64)data_high << 32);
                vcpu->host_msrs[j].index = index;
                vcpu->host_msrs[j].reserved = 0;
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 953808efe5515ceff6a3ba023a8f0d6f61850643..ee7b75b976b5c60a41dc0ba3e76651cba42b113c 100644 (file)
@@ -57,8 +57,8 @@
 
 #define DRV_MODULE_NAME                "bnx2"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "1.5.4"
-#define DRV_MODULE_RELDATE     "January 24, 2007"
+#define DRV_MODULE_VERSION     "1.5.5"
+#define DRV_MODULE_RELDATE     "February 1, 2007"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -1356,6 +1356,14 @@ bnx2_init_copper_phy(struct bnx2 *bp)
                bnx2_write_phy(bp, 0x18, 0x0400);
        }
 
+       if (bp->phy_flags & PHY_DIS_EARLY_DAC_FLAG) {
+               bnx2_write_phy(bp, MII_BNX2_DSP_ADDRESS,
+                              MII_BNX2_DSP_EXPAND_REG | 0x8);
+               bnx2_read_phy(bp, MII_BNX2_DSP_RW_PORT, &val);
+               val &= ~(1 << 8);
+               bnx2_write_phy(bp, MII_BNX2_DSP_RW_PORT, val);
+       }
+
        if (bp->dev->mtu > 1500) {
                /* Set extended packet length bit */
                bnx2_write_phy(bp, 0x18, 0x7);
@@ -5918,6 +5926,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        } else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
                   CHIP_NUM(bp) == CHIP_NUM_5708)
                bp->phy_flags |= PHY_CRC_FIX_FLAG;
+       else if (CHIP_ID(bp) == CHIP_ID_5709_A0)
+               bp->phy_flags |= PHY_DIS_EARLY_DAC_FLAG;
 
        if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
            (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
index 13b6f9b11e012050bbb91000880d082c53fe0722..ccbdf81c6599eab3a51cd31f4b3f91a72b6de35b 100644 (file)
@@ -6288,6 +6288,10 @@ struct l2_fhdr {
 
 #define BCM5708S_TX_ACTL3                      0x17
 
+#define MII_BNX2_DSP_RW_PORT                   0x15
+#define MII_BNX2_DSP_ADDRESS                   0x17
+#define MII_BNX2_DSP_EXPAND_REG                         0x0f00
+
 #define MIN_ETHERNET_PACKET_SIZE       60
 #define MAX_ETHERNET_PACKET_SIZE       1514
 #define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
@@ -6489,6 +6493,7 @@ struct bnx2 {
 #define PHY_INT_MODE_MASK_FLAG         0x300
 #define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100
 #define PHY_INT_MODE_LINK_READY_FLAG   0x200
+#define PHY_DIS_EARLY_DAC_FLAG         0x400
 
        u32                     chip_id;
        /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
@@ -6512,6 +6517,7 @@ struct bnx2 {
 #define CHIP_ID_5708_A0                        0x57080000
 #define CHIP_ID_5708_B0                        0x57081000
 #define CHIP_ID_5708_B1                        0x57081010
+#define CHIP_ID_5709_A0                        0x57090000
 
 #define CHIP_BOND_ID(bp)               (((bp)->chip_id) & 0xf)
 
index 3208dac291684c038ac70642057ccbbaa22efdbc..0cefef5e3f06878f27175d1bbcd850c4b5c36928 100644 (file)
@@ -2718,14 +2718,12 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct nic *nic = netdev_priv(netdev);
 
-#ifdef CONFIG_E100_NAPI
        if (netif_running(netdev))
                netif_poll_disable(nic->netdev);
-#endif
        del_timer_sync(&nic->watchdog);
        netif_carrier_off(nic->netdev);
-
        netif_device_detach(netdev);
+
        pci_save_state(pdev);
 
        if ((nic->flags & wol_magic) | e100_asf(nic)) {
@@ -2761,16 +2759,13 @@ static int e100_resume(struct pci_dev *pdev)
 }
 #endif /* CONFIG_PM */
 
-
 static void e100_shutdown(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct nic *nic = netdev_priv(netdev);
 
-#ifdef CONFIG_E100_NAPI
        if (netif_running(netdev))
                netif_poll_disable(nic->netdev);
-#endif
        del_timer_sync(&nic->watchdog);
        netif_carrier_off(nic->netdev);
 
index 896aa02000d73079fc1ebda3b222c90cdfe3531e..feb0ada7a0257157cc1240e08767c6bcad6f51a1 100644 (file)
@@ -113,7 +113,7 @@ config SCC_TRXECHO
 
 config BAYCOM_SER_FDX
        tristate "BAYCOM ser12 fullduplex driver for AX.25"
-       depends on AX25
+       depends on AX25 && !S390
        select CRC_CCITT
        ---help---
          This is one of two drivers for Baycom style simple amateur radio
@@ -133,7 +133,7 @@ config BAYCOM_SER_FDX
 
 config BAYCOM_SER_HDX
        tristate "BAYCOM ser12 halfduplex driver for AX.25"
-       depends on AX25
+       depends on AX25 && !S390
        select CRC_CCITT
        ---help---
          This is one of two drivers for Baycom style simple amateur radio
@@ -181,7 +181,7 @@ config BAYCOM_EPP
 
 config YAM
        tristate "YAM driver for AX.25"
-       depends on AX25
+       depends on AX25 && !S390
        help
          The YAM is a modem for packet radio which connects to the serial
          port and includes some of the functions of a Terminal Node
index 59324b1693d6e8bc8fe1aea8ef70642f3cb0a455..e8598b809228a422d3359068098f27722feb014f 100644 (file)
@@ -239,49 +239,39 @@ extern unsigned long long netxen_dma_mask;
 
 typedef u32 netxen_ctx_msg;
 
-#define _netxen_set_bits(config_word, start, bits, val)        {\
-       unsigned long long mask = (((1ULL << (bits)) - 1) << (start));  \
-       unsigned long long value = (val);       \
-       (config_word) &= ~mask; \
-       (config_word) |= (((value) << (start)) & mask); \
-}
-
 #define netxen_set_msg_peg_id(config_word, val)        \
-       _netxen_set_bits(config_word, 0, 2, val)
+       ((config_word) &= ~3, (config_word) |= val & 3)
 #define netxen_set_msg_privid(config_word)     \
-       set_bit(2, (unsigned long*)&config_word)
+       ((config_word) |= 1 << 2)
 #define netxen_set_msg_count(config_word, val) \
-       _netxen_set_bits(config_word, 3, 15, val)
+       ((config_word) &= ~(0x7fff<<3), (config_word) |= (val & 0x7fff) << 3)
 #define netxen_set_msg_ctxid(config_word, val) \
-       _netxen_set_bits(config_word, 18, 10, val)
+       ((config_word) &= ~(0x3ff<<18), (config_word) |= (val & 0x3ff) << 18)
 #define netxen_set_msg_opcode(config_word, val)        \
-       _netxen_set_bits(config_word, 28, 4, val)
+       ((config_word) &= ~(0xf<<24), (config_word) |= (val & 0xf) << 24)
 
 struct netxen_rcv_context {
-       u32 rcv_ring_addr_lo;
-       u32 rcv_ring_addr_hi;
-       u32 rcv_ring_size;
-       u32 rsrvd;
+       __le64 rcv_ring_addr;
+       __le32 rcv_ring_size;
+       __le32 rsrvd;
 };
 
 struct netxen_ring_ctx {
 
        /* one command ring */
-       u64 cmd_consumer_offset;
-       u32 cmd_ring_addr_lo;
-       u32 cmd_ring_addr_hi;
-       u32 cmd_ring_size;
-       u32 rsrvd;
+       __le64 cmd_consumer_offset;
+       __le64 cmd_ring_addr;
+       __le32 cmd_ring_size;
+       __le32 rsrvd;
 
        /* three receive rings */
        struct netxen_rcv_context rcv_ctx[3];
 
        /* one status ring */
-       u32 sts_ring_addr_lo;
-       u32 sts_ring_addr_hi;
-       u32 sts_ring_size;
+       __le64 sts_ring_addr;
+       __le32 sts_ring_size;
 
-       u32 ctx_id;
+       __le32 ctx_id;
 } __attribute__ ((aligned(64)));
 
 /*
@@ -305,81 +295,85 @@ struct netxen_ring_ctx {
        ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
 
 #define netxen_set_cmd_desc_flags(cmd_desc, val)       \
-       _netxen_set_bits((cmd_desc)->flags_opcode, 0, 7, val)
+       ((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x7f), \
+       (cmd_desc)->flags_opcode |= cpu_to_le16((val) & 0x7f))
 #define netxen_set_cmd_desc_opcode(cmd_desc, val)      \
-       _netxen_set_bits((cmd_desc)->flags_opcode, 7, 6, val)
+       ((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x3f<<7), \
+       (cmd_desc)->flags_opcode |= cpu_to_le16((val) & (0x3f<<7)))
 
 #define netxen_set_cmd_desc_num_of_buff(cmd_desc, val) \
-       _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 0, 8, val);
+       ((cmd_desc)->num_of_buffers_total_length &= ~cpu_to_le32(0xff), \
+       (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32((val) & 0xff))
 #define netxen_set_cmd_desc_totallength(cmd_desc, val) \
-       _netxen_set_bits((cmd_desc)->num_of_buffers_total_length, 8, 24, val);
+       ((cmd_desc)->num_of_buffers_total_length &= cpu_to_le32(0xff), \
+       (cmd_desc)->num_of_buffers_total_length |= cpu_to_le32(val << 24))
 
 #define netxen_get_cmd_desc_opcode(cmd_desc)   \
-       (((cmd_desc)->flags_opcode >> 7) & 0x003F)
+       ((le16_to_cpu((cmd_desc)->flags_opcode) >> 7) & 0x003F)
 #define netxen_get_cmd_desc_totallength(cmd_desc)      \
-       (((cmd_desc)->num_of_buffers_total_length >> 8) & 0x0FFFFFF)
+       (le32_to_cpu((cmd_desc)->num_of_buffers_total_length) >> 8)
 
 struct cmd_desc_type0 {
        u8 tcp_hdr_offset;      /* For LSO only */
        u8 ip_hdr_offset;       /* For LSO only */
        /* Bit pattern: 0-6 flags, 7-12 opcode, 13-15 unused */
-       u16 flags_opcode;
+       __le16 flags_opcode;
        /* Bit pattern: 0-7 total number of segments,
           8-31 Total size of the packet */
-       u32 num_of_buffers_total_length;
+       __le32 num_of_buffers_total_length;
        union {
                struct {
-                       u32 addr_low_part2;
-                       u32 addr_high_part2;
+                       __le32 addr_low_part2;
+                       __le32 addr_high_part2;
                };
-               u64 addr_buffer2;
+               __le64 addr_buffer2;
        };
 
-       u16 reference_handle;   /* changed to u16 to add mss */
-       u16 mss;                /* passed by NDIS_PACKET for LSO */
+       __le16 reference_handle;        /* changed to u16 to add mss */
+       __le16 mss;             /* passed by NDIS_PACKET for LSO */
        /* Bit pattern 0-3 port, 0-3 ctx id */
        u8 port_ctxid;
        u8 total_hdr_length;    /* LSO only : MAC+IP+TCP Hdr size */
-       u16 conn_id;            /* IPSec offoad only */
+       __le16 conn_id;         /* IPSec offoad only */
 
        union {
                struct {
-                       u32 addr_low_part3;
-                       u32 addr_high_part3;
+                       __le32 addr_low_part3;
+                       __le32 addr_high_part3;
                };
-               u64 addr_buffer3;
+               __le64 addr_buffer3;
        };
        union {
                struct {
-                       u32 addr_low_part1;
-                       u32 addr_high_part1;
+                       __le32 addr_low_part1;
+                       __le32 addr_high_part1;
                };
-               u64 addr_buffer1;
+               __le64 addr_buffer1;
        };
 
-       u16 buffer1_length;
-       u16 buffer2_length;
-       u16 buffer3_length;
-       u16 buffer4_length;
+       __le16 buffer1_length;
+       __le16 buffer2_length;
+       __le16 buffer3_length;
+       __le16 buffer4_length;
 
        union {
                struct {
-                       u32 addr_low_part4;
-                       u32 addr_high_part4;
+                       __le32 addr_low_part4;
+                       __le32 addr_high_part4;
                };
-               u64 addr_buffer4;
+               __le64 addr_buffer4;
        };
 
-       u64 unused;
+       __le64 unused;
 
 } __attribute__ ((aligned(64)));
 
 /* Note: sizeof(rcv_desc) should always be a mutliple of 2 */
 struct rcv_desc {
-       u16 reference_handle;
-       u16 reserved;
-       u32 buffer_length;      /* allocated buffer length (usually 2K) */
-       u64 addr_buffer;
+       __le16 reference_handle;
+       __le16 reserved;
+       __le32 buffer_length;   /* allocated buffer length (usually 2K) */
+       __le64 addr_buffer;
 };
 
 /* opcode field in status_desc */
@@ -405,36 +399,36 @@ struct rcv_desc {
        (((status_desc)->lro & 0x80) >> 7)
 
 #define netxen_get_sts_port(status_desc)       \
-       ((status_desc)->status_desc_data & 0x0F)
+       (le64_to_cpu((status_desc)->status_desc_data) & 0x0F)
 #define netxen_get_sts_status(status_desc)     \
-       (((status_desc)->status_desc_data >> 4) & 0x0F)
+       ((le64_to_cpu((status_desc)->status_desc_data) >> 4) & 0x0F)
 #define netxen_get_sts_type(status_desc)       \
-       (((status_desc)->status_desc_data >> 8) & 0x0F)
+       ((le64_to_cpu((status_desc)->status_desc_data) >> 8) & 0x0F)
 #define netxen_get_sts_totallength(status_desc)        \
-       (((status_desc)->status_desc_data >> 12) & 0xFFFF)
+       ((le64_to_cpu((status_desc)->status_desc_data) >> 12) & 0xFFFF)
 #define netxen_get_sts_refhandle(status_desc)  \
-       (((status_desc)->status_desc_data >> 28) & 0xFFFF)
+       ((le64_to_cpu((status_desc)->status_desc_data) >> 28) & 0xFFFF)
 #define netxen_get_sts_prot(status_desc)       \
-       (((status_desc)->status_desc_data >> 44) & 0x0F)
+       ((le64_to_cpu((status_desc)->status_desc_data) >> 44) & 0x0F)
 #define netxen_get_sts_owner(status_desc)      \
-       (((status_desc)->status_desc_data >> 56) & 0x03)
+       ((le64_to_cpu((status_desc)->status_desc_data) >> 56) & 0x03)
 #define netxen_get_sts_opcode(status_desc)     \
-       (((status_desc)->status_desc_data >> 58) & 0x03F)
+       ((le64_to_cpu((status_desc)->status_desc_data) >> 58) & 0x03F)
 
 #define netxen_clear_sts_owner(status_desc)    \
        ((status_desc)->status_desc_data &=     \
-       ~(((unsigned long long)3) << 56 ))
+       ~cpu_to_le64(((unsigned long long)3) << 56 ))
 #define netxen_set_sts_owner(status_desc, val) \
        ((status_desc)->status_desc_data |=     \
-       (((unsigned long long)((val) & 0x3)) << 56 ))
+       cpu_to_le64(((unsigned long long)((val) & 0x3)) << 56 ))
 
 struct status_desc {
        /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
           28-43 reference_handle, 44-47 protocol, 48-52 unused
           53-55 desc_cnt, 56-57 owner, 58-63 opcode
         */
-       u64 status_desc_data;
-       u32 hash_value;
+       __le64 status_desc_data;
+       __le32 hash_value;
        u8 hash_type;
        u8 msg_type;
        u8 unused;
@@ -1005,9 +999,9 @@ void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, int port,
 void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, int port,
                                  long enable);
 int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, long reg,
-                           __le32 * readval);
+                           __u32 * readval);
 int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long phy,
-                            long reg, __le32 val);
+                            long reg, __u32 val);
 
 /* Functions available from netxen_nic_hw.c */
 int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu);
index 34044616b3c8cf20a5b99d1d348c999eda9477dc..c381d77a7336a1acb6536f2bbb956b7228bf6e4c 100644 (file)
@@ -218,7 +218,7 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
-       __le32 status;
+       __u32 status;
 
        /* read which mode */
        if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
@@ -226,7 +226,7 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                if (adapter->phy_write
                    && adapter->phy_write(adapter, port->portnum,
                                          NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-                                         (__le32) ecmd->autoneg) != 0)
+                                         ecmd->autoneg) != 0)
                        return -EIO;
                else
                        port->link_autoneg = ecmd->autoneg;
@@ -279,7 +279,7 @@ static int netxen_nic_get_regs_len(struct net_device *dev)
 }
 
 struct netxen_niu_regs {
-       __le32 reg[NETXEN_NIC_REGS_COUNT];
+       __u32 reg[NETXEN_NIC_REGS_COUNT];
 };
 
 static struct netxen_niu_regs niu_registers[] = {
@@ -372,7 +372,7 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
 {
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
-       __le32 mode, *regs_buff = p;
+       __u32 mode, *regs_buff = p;
        void __iomem *addr;
        int i, window;
 
@@ -415,7 +415,7 @@ static u32 netxen_nic_get_link(struct net_device *dev)
 {
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
-       __le32 status;
+       __u32 status;
 
        /* read which mode */
        if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
@@ -482,13 +482,13 @@ netxen_nic_get_pauseparam(struct net_device *dev,
 {
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
-       __le32 val;
+       __u32 val;
 
        if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
                /* get flow control settings */
                netxen_nic_read_w0(adapter,
                                   NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
-                                  (u32 *) & val);
+                                  &val);
                pause->rx_pause = netxen_gb_get_rx_flowctl(val);
                pause->tx_pause = netxen_gb_get_tx_flowctl(val);
                /* get autoneg settings */
@@ -502,7 +502,7 @@ netxen_nic_set_pauseparam(struct net_device *dev,
 {
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
-       __le32 val;
+       __u32 val;
        unsigned int autoneg;
 
        /* read mode */
@@ -522,13 +522,13 @@ netxen_nic_set_pauseparam(struct net_device *dev,
 
                netxen_nic_write_w0(adapter,
                                    NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum),
-                                   *(u32 *) (&val));
+                                   *&val);
                /* set autoneg */
                autoneg = pause->autoneg;
                if (adapter->phy_write
                    && adapter->phy_write(adapter, port->portnum,
                                          NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-                                         (__le32) autoneg) != 0)
+                                         autoneg) != 0)
                        return -EIO;
                else {
                        port->link_autoneg = pause->autoneg;
@@ -543,7 +543,7 @@ static int netxen_nic_reg_test(struct net_device *dev)
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
        u32 data_read, data_written, save;
-       __le32 mode;
+       __u32 mode;
 
        /* 
         * first test the "Read Only" registers by writing which mode
index 191e2336e3234b9db39cbf1f0c4bf54b75b29bed..f263232f499fdc56fc7cc0837bc4783d12d62c0f 100644 (file)
@@ -95,7 +95,7 @@ void netxen_nic_set_multi(struct net_device *netdev)
        struct netxen_port *port = netdev_priv(netdev);
        struct netxen_adapter *adapter = port->adapter;
        struct dev_mc_list *mc_ptr;
-       __le32 netxen_mac_addr_cntl_data = 0;
+       __u32 netxen_mac_addr_cntl_data = 0;
 
        mc_ptr = netdev->mc_list;
        if (netdev->flags & IFF_PROMISC) {
@@ -236,8 +236,9 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
        }
        memset(addr, 0, sizeof(struct netxen_ring_ctx));
        adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
-       adapter->ctx_desc->cmd_consumer_offset = adapter->ctx_desc_phys_addr
-           + sizeof(struct netxen_ring_ctx);
+       adapter->ctx_desc->cmd_consumer_offset =
+           cpu_to_le64(adapter->ctx_desc_phys_addr +
+                       sizeof(struct netxen_ring_ctx));
        adapter->cmd_consumer = (uint32_t *) (((char *)addr) +
                                              sizeof(struct netxen_ring_ctx));
 
@@ -253,11 +254,10 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
                return -ENOMEM;
        }
 
-       adapter->ctx_desc->cmd_ring_addr_lo =
-           hw->cmd_desc_phys_addr & 0xffffffffUL;
-       adapter->ctx_desc->cmd_ring_addr_hi =
-           ((u64) hw->cmd_desc_phys_addr >> 32);
-       adapter->ctx_desc->cmd_ring_size = adapter->max_tx_desc_count;
+       adapter->ctx_desc->cmd_ring_addr =
+               cpu_to_le64(hw->cmd_desc_phys_addr);
+       adapter->ctx_desc->cmd_ring_size =
+               cpu_to_le32(adapter->max_tx_desc_count);
 
        hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
 
@@ -278,12 +278,10 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
                                return err;
                        }
                        rcv_desc->desc_head = (struct rcv_desc *)addr;
-                       adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_lo =
-                           rcv_desc->phys_addr & 0xffffffffUL;
-                       adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr_hi =
-                           ((u64) rcv_desc->phys_addr >> 32);
+                       adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
+                           cpu_to_le64(rcv_desc->phys_addr);
                        adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
-                           rcv_desc->max_rx_desc_count;
+                           cpu_to_le32(rcv_desc->max_rx_desc_count);
                }
 
                addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE,
@@ -297,11 +295,10 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
                        return err;
                }
                recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
-               adapter->ctx_desc->sts_ring_addr_lo =
-                   recv_ctx->rcv_status_desc_phys_addr & 0xffffffffUL;
-               adapter->ctx_desc->sts_ring_addr_hi =
-                   ((u64) recv_ctx->rcv_status_desc_phys_addr >> 32);
-               adapter->ctx_desc->sts_ring_size = adapter->max_rx_desc_count;
+               adapter->ctx_desc->sts_ring_addr =
+                   cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
+               adapter->ctx_desc->sts_ring_size =
+                   cpu_to_le32(adapter->max_rx_desc_count);
 
        }
        /* Window = 1 */
@@ -387,10 +384,6 @@ void netxen_tso_check(struct netxen_adapter *adapter,
        }
        adapter->stats.xmitcsummed++;
        desc->tcp_hdr_offset = skb->h.raw - skb->data;
-       netxen_set_cmd_desc_totallength(desc,
-                                       cpu_to_le32
-                                       (netxen_get_cmd_desc_totallength
-                                        (desc)));
        desc->ip_hdr_offset = skb->nh.raw - skb->data;
 }
 
@@ -867,9 +860,9 @@ netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off,
 void netxen_nic_set_link_parameters(struct netxen_port *port)
 {
        struct netxen_adapter *adapter = port->adapter;
-       __le32 status;
-       __le32 autoneg;
-       __le32 mode;
+       __u32 status;
+       __u32 autoneg;
+       __u32 mode;
 
        netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
        if (netxen_get_niu_enable_ge(mode)) {   /* Gb 10/100/1000 Mbps mode */
index 0685633a9c1ea9e4626339246fcd1779fe2ebe0e..ab1112eb1b0d0e49f7eebbdd30017c8e0090c9de 100644 (file)
@@ -124,28 +124,28 @@ typedef enum {
  */
 
 #define netxen_gb_enable_tx(config_word)       \
-       set_bit(0, (unsigned long*)(&config_word))
+       ((config_word) |= 1 << 0)
 #define netxen_gb_enable_rx(config_word)       \
-       set_bit(2, (unsigned long*)(&config_word))
+       ((config_word) |= 1 << 2)
 #define netxen_gb_tx_flowctl(config_word)      \
-       set_bit(4, (unsigned long*)(&config_word))
+       ((config_word) |= 1 << 4)
 #define netxen_gb_rx_flowctl(config_word)      \
-       set_bit(5, (unsigned long*)(&config_word))
+       ((config_word) |= 1 << 5)
 #define netxen_gb_tx_reset_pb(config_word)     \
-               set_bit(16, (unsigned long*)(&config_word))
+       ((config_word) |= 1 << 16)
 #define netxen_gb_rx_reset_pb(config_word)     \
-               set_bit(17, (unsigned long*)(&config_word))
+       ((config_word) |= 1 << 17)
 #define netxen_gb_tx_reset_mac(config_word)    \
-               set_bit(18, (unsigned long*)(&config_word))
+       ((config_word) |= 1 << 18)
 #define netxen_gb_rx_reset_mac(config_word)    \
-               set_bit(19, (unsigned long*)(&config_word))
+       ((config_word) |= 1 << 19)
 #define netxen_gb_soft_reset(config_word)      \
-               set_bit(31, (unsigned long*)(&config_word))
+       ((config_word) |= 1 << 31)
 
 #define netxen_gb_unset_tx_flowctl(config_word)        \
-               clear_bit(4, (unsigned long *)(&config_word))
+       ((config_word) &= ~(1 << 4))
 #define netxen_gb_unset_rx_flowctl(config_word)        \
-               clear_bit(5, (unsigned long*)(&config_word))
+       ((config_word) &= ~(1 << 5))
 
 #define netxen_gb_get_tx_synced(config_word)   \
                _netxen_crb_get_bit((config_word), 1)
@@ -171,15 +171,15 @@ typedef enum {
  */
 
 #define netxen_gb_set_duplex(config_word)      \
-               set_bit(0, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 0)
 #define netxen_gb_set_crc_enable(config_word)  \
-               set_bit(1, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 1)
 #define netxen_gb_set_padshort(config_word)    \
-               set_bit(2, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 2)
 #define netxen_gb_set_checklength(config_word) \
-               set_bit(4, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 4)
 #define netxen_gb_set_hugeframes(config_word)  \
-               set_bit(5, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 5)
 #define netxen_gb_set_preamblelen(config_word, val)    \
                ((config_word) |= ((val) << 12) & 0xF000)
 #define netxen_gb_set_intfmode(config_word, val)               \
@@ -190,9 +190,9 @@ typedef enum {
 #define netxen_gb_set_mii_mgmt_clockselect(config_word, val)   \
                ((config_word) |= ((val) & 0x07))
 #define netxen_gb_mii_mgmt_reset(config_word)  \
-               set_bit(31, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 31)
 #define netxen_gb_mii_mgmt_unset(config_word)  \
-               clear_bit(31, (unsigned long*)&config_word)
+               ((config_word) &= ~(1 << 31))
 
 /*
  * NIU GB MII Mgmt Command Register (applies to GB0, GB1, GB2, GB3)
@@ -201,7 +201,7 @@ typedef enum {
  */
 
 #define netxen_gb_mii_mgmt_set_read_cycle(config_word) \
-               set_bit(0, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 0)
 #define netxen_gb_mii_mgmt_reg_addr(config_word, val)  \
                ((config_word) |= ((val) & 0x1F))
 #define netxen_gb_mii_mgmt_phy_addr(config_word, val)  \
@@ -274,9 +274,9 @@ typedef enum {
 #define netxen_set_phy_speed(config_word, val) \
                ((config_word) |= ((val & 0x03) << 14))
 #define netxen_set_phy_duplex(config_word)     \
-               set_bit(13, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 13)
 #define netxen_clear_phy_duplex(config_word)   \
-               clear_bit(13, (unsigned long*)&config_word)
+               ((config_word) &= ~(1 << 13))
 
 #define netxen_get_phy_jabber(config_word)     \
                _netxen_crb_get_bit(config_word, 0)
@@ -350,11 +350,11 @@ typedef enum {
                _netxen_crb_get_bit(config_word, 15)
 
 #define netxen_set_phy_int_link_status_changed(config_word)    \
-               set_bit(10, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 10)
 #define netxen_set_phy_int_autoneg_completed(config_word)      \
-               set_bit(11, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 11)
 #define netxen_set_phy_int_speed_changed(config_word)  \
-               set_bit(14, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 14)
 
 /*
  * NIU Mode Register.
@@ -382,22 +382,22 @@ typedef enum {
  */
 
 #define netxen_set_gb_drop_gb0(config_word)    \
-               set_bit(0, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 0)
 #define netxen_set_gb_drop_gb1(config_word)    \
-               set_bit(1, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 1)
 #define netxen_set_gb_drop_gb2(config_word)    \
-               set_bit(2, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 2)
 #define netxen_set_gb_drop_gb3(config_word)    \
-               set_bit(3, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 3)
 
 #define netxen_clear_gb_drop_gb0(config_word)  \
-               clear_bit(0, (unsigned long*)&config_word)
+               ((config_word) &= ~(1 << 0))
 #define netxen_clear_gb_drop_gb1(config_word)  \
-               clear_bit(1, (unsigned long*)&config_word)
+               ((config_word) &= ~(1 << 1))
 #define netxen_clear_gb_drop_gb2(config_word)  \
-               clear_bit(2, (unsigned long*)&config_word)
+               ((config_word) &= ~(1 << 2))
 #define netxen_clear_gb_drop_gb3(config_word)  \
-               clear_bit(3, (unsigned long*)&config_word)
+               ((config_word) &= ~(1 << 3))
 
 /*
  * NIU XG MAC Config Register
@@ -413,7 +413,7 @@ typedef enum {
  */
 
 #define netxen_xg_soft_reset(config_word)      \
-               set_bit(4, (unsigned long*)&config_word)
+               ((config_word) |= 1 << 4)
 
 /*
  * MAC Control Register
@@ -433,19 +433,19 @@ typedef enum {
 #define netxen_nic_mcr_set_id_pool0(config, val)       \
                ((config) |= ((val) &0x03))
 #define netxen_nic_mcr_set_enable_xtnd0(config)        \
-               (set_bit(3, (unsigned long *)&(config)))
+               ((config) |= 1 << 3)
 #define netxen_nic_mcr_set_id_pool1(config, val)       \
                ((config) |= (((val) & 0x03) << 4))
 #define netxen_nic_mcr_set_enable_xtnd1(config)        \
-               (set_bit(6, (unsigned long *)&(config)))
+               ((config) |= 1 << 6)
 #define netxen_nic_mcr_set_id_pool2(config, val)       \
                ((config) |= (((val) & 0x03) << 8))
 #define netxen_nic_mcr_set_enable_xtnd2(config)        \
-               (set_bit(10, (unsigned long *)&(config)))
+               ((config) |= 1 << 10)
 #define netxen_nic_mcr_set_id_pool3(config, val)       \
                ((config) |= (((val) & 0x03) << 12))
 #define netxen_nic_mcr_set_enable_xtnd3(config)        \
-               (set_bit(14, (unsigned long *)&(config)))
+               ((config) |= 1 << 14)
 #define netxen_nic_mcr_set_mode_select(config, val)    \
                ((config) |= (((val) & 0x03) << 24))
 #define netxen_nic_mcr_set_enable_pool(config, val)    \
index c3e41f368554b6e3c321e21e66041fc77bd72013..973af96337a922dc150d38639ebdfeef63b6ae75 100644 (file)
@@ -690,8 +690,7 @@ int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
                desc_head = recv_ctx->rcv_status_desc_head;
                desc = &desc_head[consumer];
 
-               if (((le16_to_cpu(netxen_get_sts_owner(desc)))
-                    & STATUS_OWNER_HOST))
+               if (netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)
                        return 1;
        }
 
@@ -787,11 +786,11 @@ netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
        struct netxen_port *port = adapter->port[netxen_get_sts_port(desc)];
        struct pci_dev *pdev = port->pdev;
        struct net_device *netdev = port->netdev;
-       int index = le16_to_cpu(netxen_get_sts_refhandle(desc));
+       int index = netxen_get_sts_refhandle(desc);
        struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]);
        struct netxen_rx_buffer *buffer;
        struct sk_buff *skb;
-       u32 length = le16_to_cpu(netxen_get_sts_totallength(desc));
+       u32 length = netxen_get_sts_totallength(desc);
        u32 desc_ctx;
        struct netxen_rcv_desc_ctx *rcv_desc;
        int ret;
@@ -918,16 +917,14 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
         */
        while (count < max) {
                desc = &desc_head[consumer];
-               if (!
-                   (le16_to_cpu(netxen_get_sts_owner(desc)) &
-                    STATUS_OWNER_HOST)) {
+               if (!(netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)) {
                        DPRINTK(ERR, "desc %p ownedby %x\n", desc,
                                netxen_get_sts_owner(desc));
                        break;
                }
                netxen_process_rcv(adapter, ctxid, desc);
                netxen_clear_sts_owner(desc);
-               netxen_set_sts_owner(desc, cpu_to_le16(STATUS_OWNER_PHANTOM));
+               netxen_set_sts_owner(desc, STATUS_OWNER_PHANTOM);
                consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
                count++;
        }
@@ -1232,7 +1229,7 @@ void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, uint32_t ctx,
 
                /* make a rcv descriptor  */
                pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
-               pdesc->buffer_length = cpu_to_le16(rcv_desc->dma_size);
+               pdesc->buffer_length = cpu_to_le32(rcv_desc->dma_size);
                pdesc->addr_buffer = cpu_to_le64(buffer->dma);
                DPRINTK(INFO, "done writing descripter\n");
                producer =
index 06847d4252c338b7e47b31ff63f2d03f773c1651..be366e48007c9e96e3fd0554161896ddd1933c73 100644 (file)
@@ -79,7 +79,7 @@ void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 portno,
 void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno,
                            u32 enable)
 {
-       __le32 int_src;
+       __u32 int_src;
        struct netxen_port *port;
 
        /*  This should clear the interrupt source */
@@ -110,7 +110,7 @@ void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno,
        /* write it down later.. */
        if ((netxen_get_phy_int_speed_changed(int_src))
            || (netxen_get_phy_int_link_status_changed(int_src))) {
-               __le32 status;
+               __u32 status;
 
                DPRINTK(INFO, "SPEED CHANGED OR LINK STATUS CHANGED \n");
 
index 96e1bee19ba0b4cdd98a5284faaefd6883ebacb2..69c1b9d23a1aecaa99d2b6d752f9d5c1cf9e749c 100644 (file)
@@ -117,7 +117,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        void __iomem *mem_ptr1 = NULL;
        void __iomem *mem_ptr2 = NULL;
 
-       u8 *db_ptr = NULL;
+       u8 __iomem *db_ptr = NULL;
        unsigned long mem_base, mem_len, db_base, db_len;
        int pci_using_dac, i, err;
        int ring;
@@ -191,7 +191,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                db_len);
 
        db_ptr = ioremap(db_base, NETXEN_DB_MAPSIZE_BYTES);
-       if (db_ptr == 0UL) {
+       if (!db_ptr) {
                printk(KERN_ERR "%s: Failed to allocate doorbell map.",
                       netxen_nic_driver_name);
                err = -EIO;
@@ -818,7 +818,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        /* Take skb->data itself */
        pbuf = &adapter->cmd_buf_arr[producer];
        if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) {
-               pbuf->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+               pbuf->mss = skb_shinfo(skb)->gso_size;
                hwdesc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
        } else {
                pbuf->mss = 0;
@@ -882,7 +882,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                        hwdesc->addr_buffer3 = cpu_to_le64(temp_dma);
                        break;
                case 3:
-                       hwdesc->buffer4_length = temp_len;
+                       hwdesc->buffer4_length = cpu_to_le16(temp_len);
                        hwdesc->addr_buffer4 = cpu_to_le64(temp_dma);
                        break;
                }
index 4987dc765d99017391a0f29f0612a61e46fa874c..40d7003a371caf4d06dd9d0cd91aa84ce1845bc7 100644 (file)
@@ -89,15 +89,15 @@ static inline int phy_unlock(struct netxen_adapter *adapter)
  *
  */
 int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
-                           long reg, __le32 * readval)
+                           long reg, __u32 * readval)
 {
        long timeout = 0;
        long result = 0;
        long restore = 0;
-       __le32 address;
-       __le32 command;
-       __le32 status;
-       __le32 mac_cfg0;
+       __u32 address;
+       __u32 command;
+       __u32 status;
+       __u32 mac_cfg0;
 
        if (phy_lock(adapter) != 0) {
                return -1;
@@ -112,7 +112,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
                                  &mac_cfg0, 4))
                return -EIO;
        if (netxen_gb_get_soft_reset(mac_cfg0)) {
-               __le32 temp;
+               __u32 temp;
                temp = 0;
                netxen_gb_tx_reset_pb(temp);
                netxen_gb_rx_reset_pb(temp);
@@ -184,15 +184,15 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy,
  *
  */
 int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
-                            long phy, long reg, __le32 val)
+                            long phy, long reg, __u32 val)
 {
        long timeout = 0;
        long result = 0;
        long restore = 0;
-       __le32 address;
-       __le32 command;
-       __le32 status;
-       __le32 mac_cfg0;
+       __u32 address;
+       __u32 command;
+       __u32 status;
+       __u32 mac_cfg0;
 
        /*
         * MII mgmt all goes through port 0 MAC interface, so it
@@ -203,7 +203,7 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
                                  &mac_cfg0, 4))
                return -EIO;
        if (netxen_gb_get_soft_reset(mac_cfg0)) {
-               __le32 temp;
+               __u32 temp;
                temp = 0;
                netxen_gb_tx_reset_pb(temp);
                netxen_gb_rx_reset_pb(temp);
@@ -269,7 +269,7 @@ int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter,
                                         int port)
 {
        int result = 0;
-       __le32 enable = 0;
+       __u32 enable = 0;
        netxen_set_phy_int_link_status_changed(enable);
        netxen_set_phy_int_autoneg_completed(enable);
        netxen_set_phy_int_speed_changed(enable);
@@ -402,7 +402,7 @@ void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter,
 int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
 {
        int result = 0;
-       __le32 status;
+       __u32 status;
        if (adapter->disable_phy_interrupts)
                adapter->disable_phy_interrupts(adapter, port);
        mdelay(2);
@@ -410,7 +410,7 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port)
        if (0 ==
            netxen_niu_gbe_phy_read(adapter, port,
                                    NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-                                   (__le32 *) & status)) {
+                                   &status)) {
                if (netxen_get_phy_link(status)) {
                        if (netxen_get_phy_speed(status) == 2) {
                                netxen_niu_gbe_set_gmii_mode(adapter, port, 1);
@@ -489,7 +489,7 @@ int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
                                        int port, long enable)
 {
        int result = 0;
-       __le32 int_src;
+       __u32 int_src;
 
        printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d"
               " (device enable = %d)\n", (int)port, (int)enable);
@@ -530,7 +530,7 @@ int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
                        printk(KERN_INFO PFX "autoneg_error ");
                if ((netxen_get_phy_int_speed_changed(int_src))
                    || (netxen_get_phy_int_link_status_changed(int_src))) {
-                       __le32 status;
+                       __u32 status;
 
                        printk(KERN_INFO PFX
                               "speed_changed or link status changed");
@@ -583,9 +583,9 @@ int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter,
 int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
                           int phy, netxen_ethernet_macaddr_t * addr)
 {
-       u64 result = 0;
-       __le32 stationhigh;
-       __le32 stationlow;
+       u32 stationhigh;
+       u32 stationlow;
+       u8 val[8];
 
        if (addr == NULL)
                return -EINVAL;
@@ -598,10 +598,10 @@ int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
        if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy),
                                  &stationlow, 4))
                return -EIO;
+       ((__le32 *)val)[1] = cpu_to_le32(stationhigh);
+       ((__le32 *)val)[0] = cpu_to_le32(stationlow);
 
-       result = (u64) netxen_gb_get_stationaddress_low(stationlow);
-       result |= (u64) stationhigh << 16;
-       memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+       memcpy(addr, val + 2, 6);
 
        return 0;
 }
@@ -613,24 +613,25 @@ int netxen_niu_macaddr_get(struct netxen_adapter *adapter,
 int netxen_niu_macaddr_set(struct netxen_port *port,
                           netxen_ethernet_macaddr_t addr)
 {
-       __le32 temp = 0;
+       u8 temp[4];
+       u32 val;
        struct netxen_adapter *adapter = port->adapter;
        int phy = port->portnum;
        unsigned char mac_addr[6];
        int i;
 
        for (i = 0; i < 10; i++) {
-               memcpy(&temp, addr, 2);
-               temp <<= 16;
+               temp[0] = temp[1] = 0;
+               memcpy(temp + 2, addr, 2);
+               val = le32_to_cpu(*(__le32 *)temp);
                if (netxen_nic_hw_write_wx
-                   (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &temp, 4))
+                   (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &val, 4))
                        return -EIO;
 
-               temp = 0;
-
-               memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
+               memcpy(temp, ((u8 *) addr) + 2, sizeof(__le32));
+               val = le32_to_cpu(*(__le32 *)temp);
                if (netxen_nic_hw_write_wx
-                   (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &temp, 4))
+                   (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &val, 4))
                        return -2;
 
                netxen_niu_macaddr_get(adapter, phy,
@@ -659,9 +660,9 @@ int netxen_niu_macaddr_set(struct netxen_port *port,
 int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
                               int port, netxen_niu_gbe_ifmode_t mode)
 {
-       __le32 mac_cfg0;
-       __le32 mac_cfg1;
-       __le32 mii_cfg;
+       __u32 mac_cfg0;
+       __u32 mac_cfg1;
+       __u32 mii_cfg;
 
        if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
                return -EINVAL;
@@ -736,7 +737,7 @@ int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter,
 /* Disable a GbE interface */
 int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port)
 {
-       __le32 mac_cfg0;
+       __u32 mac_cfg0;
 
        if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
                return -EINVAL;
@@ -752,7 +753,7 @@ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port)
 /* Disable an XG interface */
 int netxen_niu_disable_xg_port(struct netxen_adapter *adapter, int port)
 {
-       __le32 mac_cfg;
+       __u32 mac_cfg;
 
        if (port != 0)
                return -EINVAL;
@@ -769,7 +770,7 @@ int netxen_niu_disable_xg_port(struct netxen_adapter *adapter, int port)
 int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int port,
                                    netxen_niu_prom_mode_t mode)
 {
-       __le32 reg;
+       __u32 reg;
 
        if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
                return -EINVAL;
@@ -826,22 +827,21 @@ int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int port,
 int netxen_niu_xg_macaddr_set(struct netxen_port *port,
                              netxen_ethernet_macaddr_t addr)
 {
-       __le32 temp = 0;
+       u8 temp[4];
+       u32 val;
        struct netxen_adapter *adapter = port->adapter;
 
-       memcpy(&temp, addr, 2);
-       temp = cpu_to_le32(temp);
-       temp <<= 16;
+       temp[0] = temp[1] = 0;
+       memcpy(temp + 2, addr, 2);
+       val = le32_to_cpu(*(__le32 *)temp);
        if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
-                                  &temp, 4))
+                                  &val, 4))
                return -EIO;
 
-       temp = 0;
-
        memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32));
-       temp = cpu_to_le32(temp);
+       val = le32_to_cpu(*(__le32 *)temp);
        if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI,
-                                  &temp, 4))
+                                  &val, 4))
                return -EIO;
 
        return 0;
@@ -854,9 +854,9 @@ int netxen_niu_xg_macaddr_set(struct netxen_port *port,
 int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
                              netxen_ethernet_macaddr_t * addr)
 {
-       __le32 stationhigh;
-       __le32 stationlow;
-       u64 result;
+       u32 stationhigh;
+       u32 stationlow;
+       u8 val[8];
 
        if (addr == NULL)
                return -EINVAL;
@@ -869,10 +869,10 @@ int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
        if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1,
                                  &stationlow, 4))
                return -EIO;
+       ((__le32 *)val)[1] = cpu_to_le32(stationhigh);
+       ((__le32 *)val)[0] = cpu_to_le32(stationlow);
 
-       result = ((u64) stationlow) >> 16;
-       result |= (u64) stationhigh << 16;
-       memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t));
+       memcpy(addr, val + 2, 6);
 
        return 0;
 }
@@ -880,7 +880,7 @@ int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy,
 int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter,
                                       int port, netxen_niu_prom_mode_t mode)
 {
-       __le32 reg;
+       __u32 reg;
 
        if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
                return -EINVAL;
index 880d9fdd7c670b6a31ff2e8d3282ba65b7cb40ab..43af61438449c86c90c3dcf189a035932be1ba81 100644 (file)
@@ -968,11 +968,11 @@ static void smc911x_phy_configure(struct work_struct *work)
         * We should not be called if phy_type is zero.
         */
        if (lp->phy_type == 0)
-                goto smc911x_phy_configure_exit;
+                goto smc911x_phy_configure_exit_nolock;
 
        if (smc911x_phy_reset(dev, phyaddr)) {
                printk("%s: PHY reset timed out\n", dev->name);
-               goto smc911x_phy_configure_exit;
+               goto smc911x_phy_configure_exit_nolock;
        }
        spin_lock_irqsave(&lp->lock, flags);
 
@@ -1041,6 +1041,7 @@ static void smc911x_phy_configure(struct work_struct *work)
 
 smc911x_phy_configure_exit:
        spin_unlock_irqrestore(&lp->lock, flags);
+smc911x_phy_configure_exit_nolock:
        lp->work_pending = 0;
 }
 
index ebb6aa39f9c7c18895f7c15d5858674c30f48f70..8ea2fc1b96cb8d4f5c5125808dafd08849e2ccb7 100644 (file)
@@ -1925,6 +1925,8 @@ spider_net_stop(struct net_device *netdev)
        /* release chains */
        spider_net_release_tx_chain(card, 1);
 
+       spider_net_free_rx_chain_contents(card);
+
        spider_net_free_chain(card, &card->tx_chain);
        spider_net_free_chain(card, &card->rx_chain);
 
index 16945c2ba2ca36e13a84f1d1653c879c94b15c24..c913ea4e545c3fd444a1ce0c776d3a1628a5d266 100644 (file)
@@ -661,9 +661,11 @@ static void quirk_via_bridge(struct pci_dev *dev)
        /* See what bridge we have and find the device ranges */
        switch (dev->device) {
        case PCI_DEVICE_ID_VIA_82C686:
-               /* 82C686 is special */
-               via_vlink_dev_lo = 7;
-               via_vlink_dev_hi = 7;
+               /* The VT82C686 is special, it attaches to PCI and can have
+                  any device number. All its subdevices are functions of
+                  that single device. */
+               via_vlink_dev_lo = PCI_SLOT(dev->devfn);
+               via_vlink_dev_hi = PCI_SLOT(dev->devfn);
                break;
        case PCI_DEVICE_ID_VIA_8237:
        case PCI_DEVICE_ID_VIA_8237A:
@@ -1260,8 +1262,8 @@ static void quirk_jmicron_dualfn(struct pci_dev *pdev)
                        pci_read_config_dword(pdev, 0x40, &conf);
                        /* Enable dual function mode, AHCI on fn 0, IDE fn1 */
                        /* Set the class codes correctly and then direct IDE 0 */
-                       conf &= ~0x000F0200;    /* Clear bit 9 and 16-19 */
-                       conf |=  0x00C20002;    /* Set bit 1, 17, 22, 23 */
+                       conf &= ~0x000FF200; /* Clear bit 9 and 12-19 */
+                       conf |=  0x00C2A102; /* Set 1, 8, 13, 15, 17, 22, 23 */
                        pci_write_config_dword(pdev, 0x40, conf);
 
                        /* Reconfigure so that the PCI scanner discovers the
index fab381ed853c9d20726671b99ec1199392e50ce7..b2653c4afe9e69212f8923df0574561cc049eaef 100644 (file)
@@ -200,11 +200,8 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor,
         * can cause some machines to crash.  So here we detect and flag that
         * situation and bail out early.
         */
-       if (unlikely(list_empty(&pci_devices))) {
-               printk(KERN_INFO "pci_find_subsys() called while pci_devices "
-                               "is still empty\n");
+       if (unlikely(list_empty(&pci_devices)))
                return NULL;
-       }
        down_read(&pci_bus_sem);
        n = from ? from->global_list.next : pci_devices.next;
 
@@ -278,11 +275,8 @@ pci_get_subsys(unsigned int vendor, unsigned int device,
         * can cause some machines to crash.  So here we detect and flag that
         * situation and bail out early.
         */
-       if (unlikely(list_empty(&pci_devices))) {
-               printk(KERN_NOTICE "pci_get_subsys() called while pci_devices "
-                               "is still empty\n");
+       if (unlikely(list_empty(&pci_devices)))
                return NULL;
-       }
        down_read(&pci_bus_sem);
        n = from ? from->global_list.next : pci_devices.next;
 
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 4249e52a559290a7713dc22af921933ef7b4d5f3..6f4cf2dd2f4a45a2cdf258471db05090bd2fb01a 100644 (file)
@@ -418,7 +418,6 @@ struct scsi_qla_host {
         * concurrently.
         */
        struct mutex  mbox_sem;
-       wait_queue_head_t mailbox_wait_queue;
 
        /* temporary mailbox status registers */
        volatile uint8_t mbox_status_count;
index 2122967bbf0b1a56d9bd28819745bb99aea4882a..e021eb5db2b2c6c7eb858c2092ce7c56903a47fb 100644 (file)
@@ -76,4 +76,5 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
 extern int ql4xextended_error_logging;
 extern int ql4xdiscoverywait;
 extern int ql4xdontresethba;
+extern int ql4_mod_unload;
 #endif /* _QLA4x_GBL_H */
index cc210f297a78a22e6bf3269ab275964051d48b38..b907b06d72ab4b30bd8541fa6fc1a4955b251284 100644 (file)
@@ -958,25 +958,25 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha)
        return status;
 }
 
-int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a)
+int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha)
 {
-#define QL4_LOCK_DRVR_WAIT     300
-#define QL4_LOCK_DRVR_SLEEP    100
+#define QL4_LOCK_DRVR_WAIT     30
+#define QL4_LOCK_DRVR_SLEEP    1
 
        int drvr_wait = QL4_LOCK_DRVR_WAIT;
        while (drvr_wait) {
-               if (ql4xxx_lock_drvr(a) == 0) {
-                       msleep(QL4_LOCK_DRVR_SLEEP);
+               if (ql4xxx_lock_drvr(ha) == 0) {
+                       ssleep(QL4_LOCK_DRVR_SLEEP);
                        if (drvr_wait) {
                                DEBUG2(printk("scsi%ld: %s: Waiting for "
-                                             "Global Init Semaphore...n",
-                                             a->host_no,
-                                             __func__));
+                                             "Global Init Semaphore(%d)...n",
+                                             ha->host_no,
+                                             __func__, drvr_wait));
                        }
                        drvr_wait -= QL4_LOCK_DRVR_SLEEP;
                } else {
                        DEBUG2(printk("scsi%ld: %s: Global Init Semaphore "
-                                     "acquired.n", a->host_no, __func__));
+                                     "acquired.n", ha->host_no, __func__));
                        return QLA_SUCCESS;
                }
        }
index ef975e0dc87fb9a5eef9082dbece9fab735710fa..35b9e36a0e8dbaa924a7391ae33c98765120ddef 100644 (file)
@@ -433,7 +433,6 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
                                        readl(&ha->reg->mailbox[i]);
 
                        set_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
-                       wake_up(&ha->mailbox_wait_queue);
                }
        } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) {
                /* Immediately process the AENs that don't require much work.
@@ -686,7 +685,8 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id)
                               &ha->reg->ctrl_status);
                        readl(&ha->reg->ctrl_status);
 
-                       set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
+                       if (!ql4_mod_unload)
+                               set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
 
                        break;
                } else if (intr_status & INTR_PENDING) {
index b721dc5dd7112add3a815d358b97c6fe6e30ecc0..7f28657eef3f1d60e74827d7084408299042eea3 100644 (file)
@@ -29,18 +29,30 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
        u_long wait_count;
        uint32_t intr_status;
        unsigned long flags = 0;
-       DECLARE_WAITQUEUE(wait, current);
-
-       mutex_lock(&ha->mbox_sem);
-
-       /* Mailbox code active */
-       set_bit(AF_MBOX_COMMAND, &ha->flags);
 
        /* Make sure that pointers are valid */
        if (!mbx_cmd || !mbx_sts) {
                DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
                              "pointer\n", ha->host_no, __func__));
-               goto mbox_exit;
+               return status;
+       }
+       /* Mailbox code active */
+       wait_count = MBOX_TOV * 100;
+
+       while (wait_count--) {
+               mutex_lock(&ha->mbox_sem);
+               if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
+                       set_bit(AF_MBOX_COMMAND, &ha->flags);
+                       mutex_unlock(&ha->mbox_sem);
+                       break;
+               }
+               mutex_unlock(&ha->mbox_sem);
+               if (!wait_count) {
+                       DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
+                               ha->host_no, __func__));
+                       return status;
+               }
+               msleep(10);
        }
 
        /* To prevent overwriting mailbox registers for a command that has
@@ -73,8 +85,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        /* Wait for completion */
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       add_wait_queue(&ha->mailbox_wait_queue, &wait);
 
        /*
         * If we don't want status, don't wait for the mailbox command to
@@ -83,8 +93,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
         */
        if (outCount == 0) {
                status = QLA_SUCCESS;
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&ha->mailbox_wait_queue, &wait);
                goto mbox_exit;
        }
        /* Wait for command to complete */
@@ -108,8 +116,6 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
                spin_unlock_irqrestore(&ha->hardware_lock, flags);
                msleep(10);
        }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&ha->mailbox_wait_queue, &wait);
 
        /* Check for mailbox timeout. */
        if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
@@ -155,9 +161,10 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
 mbox_exit:
+       mutex_lock(&ha->mbox_sem);
        clear_bit(AF_MBOX_COMMAND, &ha->flags);
-       clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
        mutex_unlock(&ha->mbox_sem);
+       clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
 
        return status;
 }
index 9ef693c8809aac59ef2d823798fd5592664c042c..81fb7bd44f0167131a9eb7cc8f21a0d00172d91e 100644 (file)
@@ -40,6 +40,8 @@ MODULE_PARM_DESC(ql4xextended_error_logging,
                 "Option to enable extended error logging, "
                 "Default is 0 - no logging, 1 - debug logging");
 
+int ql4_mod_unload = 0;
+
 /*
  * SCSI host template entry points
  */
@@ -422,6 +424,9 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
                goto qc_host_busy;
        }
 
+       if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags))
+               goto qc_host_busy;
+
        spin_unlock_irq(ha->host->host_lock);
 
        srb = qla4xxx_get_new_srb(ha, ddb_entry, cmd, done);
@@ -707,16 +712,12 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha)
        return stat;
 }
 
-/**
- * qla4xxx_soft_reset - performs soft reset.
- * @ha: Pointer to host adapter structure.
- **/
-int qla4xxx_soft_reset(struct scsi_qla_host *ha)
+static void qla4xxx_hw_reset(struct scsi_qla_host *ha)
 {
-       uint32_t max_wait_time;
-       unsigned long flags = 0;
-       int status = QLA_ERROR;
        uint32_t ctrl_status;
+       unsigned long flags = 0;
+
+       DEBUG2(printk(KERN_ERR "scsi%ld: %s\n", ha->host_no, __func__));
 
        spin_lock_irqsave(&ha->hardware_lock, flags);
 
@@ -733,6 +734,20 @@ int qla4xxx_soft_reset(struct scsi_qla_host *ha)
        readl(&ha->reg->ctrl_status);
 
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
+}
+
+/**
+ * qla4xxx_soft_reset - performs soft reset.
+ * @ha: Pointer to host adapter structure.
+ **/
+int qla4xxx_soft_reset(struct scsi_qla_host *ha)
+{
+       uint32_t max_wait_time;
+       unsigned long flags = 0;
+       int status = QLA_ERROR;
+       uint32_t ctrl_status;
+
+       qla4xxx_hw_reset(ha);
 
        /* Wait until the Network Reset Intr bit is cleared */
        max_wait_time = RESET_INTR_TOV;
@@ -966,10 +981,12 @@ static void qla4xxx_do_dpc(struct work_struct *work)
        struct scsi_qla_host *ha =
                container_of(work, struct scsi_qla_host, dpc_work);
        struct ddb_entry *ddb_entry, *dtemp;
+       int status = QLA_ERROR;
 
        DEBUG2(printk("scsi%ld: %s: DPC handler waking up."
-               "flags = 0x%08lx, dpc_flags = 0x%08lx\n",
-               ha->host_no, __func__, ha->flags, ha->dpc_flags));
+               "flags = 0x%08lx, dpc_flags = 0x%08lx ctrl_stat = 0x%08x\n",
+               ha->host_no, __func__, ha->flags, ha->dpc_flags,
+               readw(&ha->reg->ctrl_status)));
 
        /* Initialization not yet finished. Don't do anything yet. */
        if (!test_bit(AF_INIT_DONE, &ha->flags))
@@ -983,31 +1000,28 @@ static void qla4xxx_do_dpc(struct work_struct *work)
                        test_bit(DPC_RESET_HA, &ha->dpc_flags))
                        qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST);
 
-               if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
+               if (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) {
                        uint8_t wait_time = RESET_INTR_TOV;
-                       unsigned long flags = 0;
-
-                       qla4xxx_flush_active_srbs(ha);
 
-                       spin_lock_irqsave(&ha->hardware_lock, flags);
                        while ((readw(&ha->reg->ctrl_status) &
                                (CSR_SOFT_RESET | CSR_FORCE_SOFT_RESET)) != 0) {
                                if (--wait_time == 0)
                                        break;
-
-                               spin_unlock_irqrestore(&ha->hardware_lock,
-                                                      flags);
-
                                msleep(1000);
-
-                               spin_lock_irqsave(&ha->hardware_lock, flags);
                        }
-                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
                        if (wait_time == 0)
                                DEBUG2(printk("scsi%ld: %s: SR|FSR "
                                              "bit not cleared-- resetting\n",
                                              ha->host_no, __func__));
+                       qla4xxx_flush_active_srbs(ha);
+                       if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) {
+                               qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
+                               status = qla4xxx_initialize_adapter(ha,
+                                               PRESERVE_DDB_LIST);
+                       }
+                       clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
+                       if (status == QLA_SUCCESS)
+                               qla4xxx_enable_intrs(ha);
                }
        }
 
@@ -1062,7 +1076,7 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha)
 
        /* Issue Soft Reset to put firmware in unknown state */
        if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS)
-               qla4xxx_soft_reset(ha);
+               qla4xxx_hw_reset(ha);
 
        /* Remove timer thread, if present */
        if (ha->timer_active)
@@ -1198,7 +1212,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev,
        INIT_LIST_HEAD(&ha->free_srb_q);
 
        mutex_init(&ha->mbox_sem);
-       init_waitqueue_head(&ha->mailbox_wait_queue);
 
        spin_lock_init(&ha->hardware_lock);
 
@@ -1665,6 +1678,7 @@ no_srp_cache:
 
 static void __exit qla4xxx_module_exit(void)
 {
+       ql4_mod_unload = 1;
        pci_unregister_driver(&qla4xxx_pci_driver);
        iscsi_unregister_transport(&qla4xxx_iscsi_transport);
        kmem_cache_destroy(srb_cachep);
index 454e19c8ad685f1e7d44543c2f0f419d75b1f5be..e5183a697d1f20a4c236aa8cd20d4ef933d27e40 100644 (file)
@@ -5,4 +5,4 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION "5.00.07-k"
+#define QLA4XXX_DRIVER_VERSION "5.00.07-k1"
index b83d03c4deef1934e051358082805b93627aa4e0..96b7cbd746a84ac323d92bf6c72d0333515b3fd3 100644 (file)
@@ -1453,6 +1453,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
        struct device *parent = &shost->shost_gendev;
        struct scsi_target *starget;
 
+       if (strncmp(scsi_scan_type, "none", 4) == 0)
+               return ERR_PTR(-ENODEV);
+
+       if (!shost->async_scan)
+               scsi_complete_async_scans();
+
        starget = scsi_alloc_target(parent, channel, id);
        if (!starget)
                return ERR_PTR(-ENOMEM);
index 978bfc1e0c6a37c5edf91c916b783837a6ad4440..b781a90d6699038f4f2a0e819ca6d2a93dd619bb 100644 (file)
@@ -1647,16 +1647,6 @@ static int sd_probe(struct device *dev)
        if (error)
                goto out_put;
 
-       class_device_initialize(&sdkp->cdev);
-       sdkp->cdev.dev = &sdp->sdev_gendev;
-       sdkp->cdev.class = &sd_disk_class;
-       strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
-
-       if (class_device_add(&sdkp->cdev))
-               goto out_put;
-
-       get_device(&sdp->sdev_gendev);
-
        sdkp->device = sdp;
        sdkp->driver = &sd_template;
        sdkp->disk = gd;
@@ -1670,6 +1660,16 @@ static int sd_probe(struct device *dev)
                        sdp->timeout = SD_MOD_TIMEOUT;
        }
 
+       class_device_initialize(&sdkp->cdev);
+       sdkp->cdev.dev = &sdp->sdev_gendev;
+       sdkp->cdev.class = &sd_disk_class;
+       strncpy(sdkp->cdev.class_id, sdp->sdev_gendev.bus_id, BUS_ID_SIZE);
+
+       if (class_device_add(&sdkp->cdev))
+               goto out_put;
+
+       get_device(&sdp->sdev_gendev);
+
        gd->major = sd_major((index & 0xf0) >> 4);
        gd->first_minor = ((index & 0xf) << 4) | (index & 0xfff00);
        gd->minors = 16;
index e016e0906e1a99aa2a26728e3b9238213aafd97b..488ec7948a570766856436970a40aa2fd3813528 100644 (file)
@@ -2816,15 +2816,18 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon
 
                if (cmd_in == MTWEOF &&
                    cmdstatp->have_sense &&
-                   (cmdstatp->flags & SENSE_EOM) &&
-                   (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
-                    cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
-                   undone == 0) {
-                       ioctl_result = 0;       /* EOF written successfully at EOM */
-                       if (fileno >= 0)
-                               fileno++;
+                   (cmdstatp->flags & SENSE_EOM)) {
+                       if (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
+                           cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) {
+                               ioctl_result = 0;       /* EOF(s) written successfully at EOM */
+                               STps->eof = ST_NOEOF;
+                       } else {  /* Writing EOF(s) failed */
+                               if (fileno >= 0)
+                                       fileno -= undone;
+                               if (undone < arg)
+                                       STps->eof = ST_NOEOF;
+                       }
                        STps->drv_file = fileno;
-                       STps->eof = ST_NOEOF;
                } else if ((cmd_in == MTFSF) || (cmd_in == MTFSFM)) {
                        if (fileno >= 0)
                                STps->drv_file = fileno - undone;
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 e0eecda78ec12cac845fac5831742643db94688f..670262a38a0f25e8471ad9073ac970901f1c981f 100644 (file)
@@ -284,7 +284,8 @@ static int write_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 reg)
        u8 data[3], tmp;
 
        data[0] = phy;
-       *(data + 1) = cpu_to_le16p(&reg);
+       data[1] = reg & 0xff;
+       data[2] = (reg >> 8) & 0xff;
        tmp = indx | PHY_WRITE | PHY_GO;
        i = 0;
 
index ee20fc4240e0684bdb84485139ada96cb3925c09..55991e4132a7f30f778a7f86862b8992c59bafca 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -298,17 +298,23 @@ static void wait_for_all_aios(struct kioctx *ctx)
        struct task_struct *tsk = current;
        DECLARE_WAITQUEUE(wait, tsk);
 
+       spin_lock_irq(&ctx->ctx_lock);
        if (!ctx->reqs_active)
-               return;
+               goto out;
 
        add_wait_queue(&ctx->wait, &wait);
        set_task_state(tsk, TASK_UNINTERRUPTIBLE);
        while (ctx->reqs_active) {
+               spin_unlock_irq(&ctx->ctx_lock);
                schedule();
                set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+               spin_lock_irq(&ctx->ctx_lock);
        }
        __set_task_state(tsk, TASK_RUNNING);
        remove_wait_queue(&ctx->wait, &wait);
+
+out:
+       spin_unlock_irq(&ctx->ctx_lock);
 }
 
 /* wait_on_sync_kiocb:
@@ -424,7 +430,6 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
        ring = kmap_atomic(ctx->ring_info.ring_pages[0], KM_USER0);
        if (ctx->reqs_active < aio_ring_avail(&ctx->ring_info, ring)) {
                list_add(&req->ki_list, &ctx->active_reqs);
-               get_ioctx(ctx);
                ctx->reqs_active++;
                okay = 1;
        }
@@ -536,8 +541,6 @@ int fastcall aio_put_req(struct kiocb *req)
        spin_lock_irq(&ctx->ctx_lock);
        ret = __aio_put_req(ctx, req);
        spin_unlock_irq(&ctx->ctx_lock);
-       if (ret)
-               put_ioctx(ctx);
        return ret;
 }
 
@@ -779,8 +782,7 @@ static int __aio_run_iocbs(struct kioctx *ctx)
                 */
                iocb->ki_users++;       /* grab extra reference */
                aio_run_iocb(iocb);
-               if (__aio_put_req(ctx, iocb))  /* drop extra ref */
-                       put_ioctx(ctx);
+               __aio_put_req(ctx, iocb);
        }
        if (!list_empty(&ctx->run_list))
                return 1;
@@ -997,14 +999,10 @@ put_rq:
        /* everything turned out well, dispose of the aiocb. */
        ret = __aio_put_req(ctx, iocb);
 
-       spin_unlock_irqrestore(&ctx->ctx_lock, flags);
-
        if (waitqueue_active(&ctx->wait))
                wake_up(&ctx->wait);
 
-       if (ret)
-               put_ioctx(ctx);
-
+       spin_unlock_irqrestore(&ctx->ctx_lock, flags);
        return ret;
 }
 
index d9bdf2b3ade2922a0564a4630f3b3ce461d1c176..fc7028b685f29ab94d5db4ef26dbb897573c6af5 100644 (file)
@@ -129,6 +129,46 @@ blkdev_get_block(struct inode *inode, sector_t iblock,
        return 0;
 }
 
+static int
+blkdev_get_blocks(struct inode *inode, sector_t iblock,
+               struct buffer_head *bh, int create)
+{
+       sector_t end_block = max_block(I_BDEV(inode));
+       unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
+
+       if ((iblock + max_blocks) > end_block) {
+               max_blocks = end_block - iblock;
+               if ((long)max_blocks <= 0) {
+                       if (create)
+                               return -EIO;    /* write fully beyond EOF */
+                       /*
+                        * It is a read which is fully beyond EOF.  We return
+                        * a !buffer_mapped buffer
+                        */
+                       max_blocks = 0;
+               }
+       }
+
+       bh->b_bdev = I_BDEV(inode);
+       bh->b_blocknr = iblock;
+       bh->b_size = max_blocks << inode->i_blkbits;
+       if (max_blocks)
+               set_buffer_mapped(bh);
+       return 0;
+}
+
+static ssize_t
+blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+                       loff_t offset, unsigned long nr_segs)
+{
+       struct file *file = iocb->ki_filp;
+       struct inode *inode = file->f_mapping->host;
+
+       return blockdev_direct_IO_no_locking(rw, iocb, inode, I_BDEV(inode),
+                               iov, offset, nr_segs, blkdev_get_blocks, NULL);
+}
+
+#if 0
 static int blk_end_aio(struct bio *bio, unsigned int bytes_done, int error)
 {
        struct kiocb *iocb = bio->bi_private;
@@ -323,6 +363,7 @@ backout:
                return PTR_ERR(page);
        goto completion;
 }
+#endif
 
 static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
 {
index 98338a569dc0b496434efcddc9a50f99afd7e8ae..c59d6fbb7a6bedb71446f33808bcb90ebf667670 100644 (file)
@@ -269,7 +269,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                        "acc=%x, error=%d\n",
                        dentry->d_parent->d_name.name,
                        dentry->d_name.name,
-                       access, (error >> 24));
+                       access, ntohl(error));
        }
 out:
        if (exp && !IS_ERR(exp))
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 ff7a66850602cb4fced3a5250d74bd43d42d4d8b..1a979ea3b379931973f79c4b70703df3f237c714 100644 (file)
@@ -2328,13 +2328,23 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
 {
        struct dentry *dentry = filp->f_path.dentry;
        struct inode *inode = dentry->d_inode;
-       struct task_struct *leader = get_proc_task(inode);
+       struct task_struct *leader = NULL;
        struct task_struct *task;
        int retval = -ENOENT;
        ino_t ino;
        int tid;
        unsigned long pos = filp->f_pos;  /* avoiding "long long" filp->f_pos */
 
+       task = get_proc_task(inode);
+       if (!task)
+               goto out_no_task;
+       rcu_read_lock();
+       if (pid_alive(task)) {
+               leader = task->group_leader;
+               get_task_struct(leader);
+       }
+       rcu_read_unlock();
+       put_task_struct(task);
        if (!leader)
                goto out_no_task;
        retval = 0;
index 84313d14e78065284ea619bb9b20a90f0377bf76..e58a427012dd3c762eb9a233756d32835babe43f 100644 (file)
 #define __NR_io_cancel                 402
 #define __NR_exit_group                        405
 #define __NR_lookup_dcookie            406
-#define __NR_sys_epoll_create          407
-#define __NR_sys_epoll_ctl             408
-#define __NR_sys_epoll_wait            409
+#define __NR_epoll_create              407
+#define __NR_epoll_ctl                 408
+#define __NR_epoll_wait                        409
+/* Feb 2007: These three sys_epoll defines shouldn't be here but culling
+ * them would break userspace apps ... we'll kill them off in 2010 :) */
+#define __NR_sys_epoll_create          __NR_epoll_create
+#define __NR_sys_epoll_ctl             __NR_epoll_ctl
+#define __NR_sys_epoll_wait            __NR_epoll_wait
 #define __NR_remap_file_pages          410
 #define __NR_set_tid_address           411
 #define __NR_restart_syscall           412
index c68e1680da0173d5754d1a1df4944120a5239e58..966a9836d556a520afebaea42a613849a6d46e01 100644 (file)
@@ -1 +1,7 @@
 include include/asm-generic/Kbuild.asm
+
+header-y += registers.h
+
+unifdef-y += termios.h
+unifdef-y += ptrace.h
+unifdef-y += page.h
index 134cc0cdf6c2727201a3f5d243d1f2761d18f342..213d92fd652aa24175ddd673c52cabb932d876be 100644 (file)
@@ -76,8 +76,6 @@ extern unsigned long max_pfn;
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* __KERNEL__ */
-
 #ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC
 #define WANT_PAGE_VIRTUAL      1
 #endif
@@ -85,4 +83,6 @@ extern unsigned long max_pfn;
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+#endif /* __KERNEL__ */
+
 #endif /* _ASM_PAGE_H */
index 9a2241b8eb1e03647f3c5cadefea0cf3a6da5a2e..cf6934012b64dc70736e26073470e143b2ed11ab 100644 (file)
 #define _ASM_PTRACE_H
 
 #include <asm/registers.h>
+#ifdef __KERNEL__
 #include <asm/irq_regs.h>
 
 #define in_syscall(regs) (((regs)->tbr & TBR_TT) == TBR_TT_TRAP0)
+#endif
 
 
 #define PT_PSR         0
@@ -60,6 +62,7 @@
 #define PTRACE_GETFDPIC_EXEC   0       /* [addr] request the executable loadmap */
 #define PTRACE_GETFDPIC_INTERP 1       /* [addr] request the interpreter loadmap */
 
+#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 /*
@@ -74,6 +77,7 @@ register struct pt_regs *__frame asm("gr28");
 extern unsigned long user_stack(const struct pt_regs *);
 extern void show_regs(struct pt_regs *);
 #define profile_pc(regs) ((regs)->pc)
+#endif
 
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASM_PTRACE_H */
index b4a664e7f55c514ed9971fed4c0ff470dff8e2ac..8840cf95e8ddc175c0795bf74579b938caea8d38 100644 (file)
@@ -69,6 +69,8 @@ struct termio {
 #define N_SYNC_PPP     14
 #define N_HCI          15  /* Bluetooth HCI UART */
 
+#ifdef __KERNEL__
 #include <asm-generic/termios.h>
+#endif
 
 #endif /* _ASM_TERMIOS_H */
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)
diff --git a/include/asm-s390/sfp-util.h b/include/asm-s390/sfp-util.h
new file mode 100644 (file)
index 0000000..8cabcd2
--- /dev/null
@@ -0,0 +1,66 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) ({          \
+       unsigned int __sh = (ah);                       \
+       unsigned int __sl = (al);                       \
+       asm volatile(                                   \
+               "       alr     %1,%3\n"                \
+               "       brc     12,0f\n"                \
+               "       ahi     %0,1\n"                 \
+               "0:     alr  %0,%2"                     \
+               : "+&d" (__sh), "+d" (__sl)             \
+               : "d" (bh), "d" (bl) : "cc");           \
+       (sh) = __sh;                                    \
+       (sl) = __sl;                                    \
+})
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) ({          \
+       unsigned int __sh = (ah);                       \
+       unsigned int __sl = (al);                       \
+       asm volatile(                                   \
+               "       slr     %1,%3\n"                \
+               "       brc     3,0f\n"                 \
+               "       ahi     %0,-1\n"                \
+               "0:     slr     %0,%2"                  \
+               : "+&d" (__sh), "+d" (__sl)             \
+               : "d" (bh), "d" (bl) : "cc");           \
+       (sh) = __sh;                                    \
+       (sl) = __sl;                                    \
+})
+
+/* a umul b = a mul b + (a>=2<<31) ? b<<32:0 + (b>=2<<31) ? a<<32:0 */
+#define umul_ppmm(wh, wl, u, v) ({                     \
+       unsigned int __wh = u;                          \
+       unsigned int __wl = v;                          \
+       asm volatile(                                   \
+               "       ltr     1,%0\n"                 \
+               "       mr      0,%1\n"                 \
+               "       jnm     0f\n"                           \
+               "       alr     0,%1\n"                 \
+               "0:     ltr     %1,%1\n"                        \
+               "       jnm     1f\n"                           \
+               "       alr     0,%0\n"                 \
+               "1:     lr      %0,0\n"                 \
+               "       lr      %1,1\n"                 \
+               : "+d" (__wh), "+d" (__wl)              \
+               : : "0", "1", "cc");                    \
+       wh = __wh;                                      \
+       wl = __wl;                                      \
+})
+
+#define udiv_qrnnd(q, r, n1, n0, d)                    \
+  do { unsigned int __r;                               \
+    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));                \
+    (r) = __r;                                         \
+  } while (0)
+extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,
+                                  unsigned int , unsigned int);
+
+#define UDIV_NEEDS_NORMALIZATION 0
+
+#define abort() return 0
+
+#define __BYTE_ORDER __BIG_ENDIAN
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 267e631e9bbc345f2bbfafba3aeeade19c87d409..34518ea7bf1b5312dfe92ecdc4f11403edbad4e2 100644 (file)
@@ -151,7 +151,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
                             "xnor\t%%g0, %0, %0"
                             : "=r" (sum), "=&r" (iph)
                             : "r" (ihl), "1" (iph)
-                            : "g2", "g3", "g4", "cc");
+                            : "g2", "g3", "g4", "cc", "memory");
        return sum;
 }
 
index 188f726217766f8e45bc7dce5a130e509d9b2f68..e57ff136ee510e884ea4474a7e2f21bde36b2390 100644 (file)
@@ -408,6 +408,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 #include <asm-generic/pgtable-nopud.h>
 
+#ifdef CONFIG_HIGHMEM
+/* Clear a kernel PTE and flush it from the TLB */
+#define kpte_clear_flush(ptep, vaddr)                                  \
+do {                                                                   \
+       pte_clear(&init_mm, vaddr, ptep);                               \
+       __flush_tlb_one(vaddr);                                         \
+} while (0)
+#endif
+
 #endif
 #endif
 
index be9ec68907237f4690101216d0b5f93c5616ed95..49dbab09ef2b05ac113aebd464631be17a572ea4 100644 (file)
@@ -63,6 +63,9 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
        return (dma_addr == bad_dma_address);
 }
 
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
 extern void *dma_alloc_coherent(struct device *dev, size_t size,
                                dma_addr_t *dma_handle, gfp_t gfp);
 extern void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
index df1c91855f0efa1336181a4552e9b6fa7cfb725e..f8ebd7c1ddb3f40019fd2c14902c58ff14de23e3 100644 (file)
@@ -301,7 +301,7 @@ extern int __init efi_uart_console_only (void);
 extern void efi_initialize_iomem_resources(struct resource *code_resource,
                                        struct resource *data_resource);
 extern unsigned long efi_get_time(void);
-extern int __init efi_set_rtc_mmss(unsigned long nowtime);
+extern int efi_set_rtc_mmss(unsigned long nowtime);
 extern int is_available_memory(efi_memory_desc_t * md);
 extern struct efi_memory_map memmap;
 
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 22aa69e209057a56e67d17379c0c484214f6f5a6..91bb8ceef0b5ab04ce1a462e68505cc53942d1bf 100644 (file)
@@ -1054,6 +1054,8 @@ static inline void ata_pause(struct ata_port *ap)
 /**
  *     ata_busy_wait - Wait for a port status register
  *     @ap: Port to wait for.
+ *     @bits: bits that must be clear
+ *     @max: number of 10uS waits to perform
  *
  *     Waits up to max*10 microseconds for the selected bits in the port's
  *     status register to be cleared.
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 fc723e595cd5ba2c95499ba058636005dd9946e3..d57118da73ff04cfecc4b09b689c7bf74191dcc6 100644 (file)
@@ -1313,7 +1313,7 @@ noinline struct pt_regs * __devinit __attribute__((weak)) idle_regs(struct pt_re
        return regs;
 }
 
-struct task_struct * __devinit fork_idle(int cpu)
+struct task_struct * __cpuinit fork_idle(int cpu)
 {
        struct task_struct *task;
        struct pt_regs regs;
index 6f31fad9be13854731486737b30311c4b4f2e1a2..7f70b0886b83d4deaa97ed588f904d275d4b7be1 100644 (file)
@@ -374,9 +374,11 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
                    && ctnetlink_dump_helpinfo(skb, ct) < 0)
                        goto nfattr_failure;
 
+#ifdef CONFIG_IP_NF_CONNTRACK_MARK
                if ((events & IPCT_MARK || ct->mark)
                    && ctnetlink_dump_mark(skb, ct) < 0)
                        goto nfattr_failure;
+#endif
 
                if (events & IPCT_COUNTER_FILLING &&
                    (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
index 2a2bcb303bfa623025cbb7593b2473e7cef3ea09..80107d4909c5b88fb69c519ea7f4301b93bb63c0 100644 (file)
@@ -165,7 +165,7 @@ config NF_CONNTRACK_FTP
 
 config NF_CONNTRACK_H323
        tristate "H.323 protocol support (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && NF_CONNTRACK
+       depends on EXPERIMENTAL && NF_CONNTRACK && (IPV6 || IPV6=n)
        help
          H.323 is a VoIP signalling protocol from ITU-T. As one of the most
          important VoIP protocols, it is widely used by voice hardware and
index 811e3e782f0f2f36c4257ed778e1301172579a7c..c64f029f7052a3eadd5831d348c4ea1602a88850 100644 (file)
@@ -389,9 +389,11 @@ static int ctnetlink_conntrack_event(struct notifier_block *this,
                    && ctnetlink_dump_helpinfo(skb, ct) < 0)
                        goto nfattr_failure;
 
+#ifdef CONFIG_NF_CONNTRACK_MARK
                if ((events & IPCT_MARK || ct->mark)
                    && ctnetlink_dump_mark(skb, ct) < 0)
                        goto nfattr_failure;
+#endif
 
                if (events & IPCT_COUNTER_FILLING &&
                    (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
index a9608064a4c303cb884b0fc6913d1f68e2fd33ee..01e69138578da0cc9db6151493a3312d5573011c 100644 (file)
@@ -55,7 +55,8 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int
        struct ipt_target *target;
        int ret = 0;
 
-       target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision);
+       target = xt_request_find_target(AF_INET, t->u.user.name,
+                                       t->u.user.revision);
        if (!target)
                return -ENOENT;
 
@@ -63,9 +64,10 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int
 
        ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t),
                              table, hook, 0, 0);
-       if (ret)
+       if (ret) {
+               module_put(t->u.kernel.target->me);
                return ret;
-
+       }
        if (t->u.kernel.target->checkentry
            && !t->u.kernel.target->checkentry(table, NULL,
                                               t->u.kernel.target, t->data,
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() */
 
 /*****************************************************************************/