Merge branch 'x86/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip...
Linus Torvalds [Mon, 14 Jul 2008 20:43:24 +0000 (13:43 -0700)]
* 'x86/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (821 commits)
  x86: make 64bit hpet_set_mapping to use ioremap too, v2
  x86: get x86_phys_bits early
  x86: max_low_pfn_mapped fix #4
  x86: change _node_to_cpumask_ptr to return const ptr
  x86: I/O APIC: remove an IRQ2-mask hack
  x86: fix numaq_tsc_disable calling
  x86, e820: remove end_user_pfn
  x86: max_low_pfn_mapped fix, #3
  x86: max_low_pfn_mapped fix, #2
  x86: max_low_pfn_mapped fix, #1
  x86_64: fix delayed signals
  x86: remove conflicting nx6325 and nx6125 quirks
  x86: Recover timer_ack lost in the merge of the NMI watchdog
  x86: I/O APIC: Never configure IRQ2
  x86: L-APIC: Always fully configure IRQ0
  x86: L-APIC: Set IRQ0 as edge-triggered
  x86: merge dwarf2 headers
  x86: use AS_CFI instead of UNWIND_INFO
  x86: use ignore macro instead of hash comment
  x86: use matching CFI_ENDPROC
  ...

638 files changed:
Documentation/ABI/testing/sysfs-block
Documentation/ABI/testing/sysfs-bus-css [new file with mode: 0644]
Documentation/block/data-integrity.txt [new file with mode: 0644]
Documentation/ioctl-number.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
arch/avr32/Kconfig
arch/avr32/boards/atngw100/setup.c
arch/avr32/boards/atstk1000/atstk1002.c
arch/avr32/boards/atstk1000/atstk1003.c
arch/avr32/boards/atstk1000/atstk1004.c
arch/avr32/kernel/entry-avr32b.S
arch/avr32/kernel/signal.c
arch/avr32/kernel/time.c
arch/avr32/kernel/vmlinux.lds.S
arch/avr32/lib/io-readsb.S
arch/avr32/mach-at32ap/Makefile
arch/avr32/mach-at32ap/at32ap700x.c
arch/avr32/mach-at32ap/intc.c
arch/avr32/mach-at32ap/pdc.c [moved from arch/avr32/mach-at32ap/at32ap.c with 90% similarity]
arch/avr32/mach-at32ap/pio.c
arch/avr32/mach-at32ap/pio.h
arch/avr32/mach-at32ap/pm-at32ap700x.S
arch/avr32/mach-at32ap/pm.c [new file with mode: 0644]
arch/avr32/mach-at32ap/sdramc.h [new file with mode: 0644]
arch/avr32/mm/init.c
arch/avr32/mm/tlb.c
arch/s390/Kconfig
arch/s390/appldata/appldata.h
arch/s390/appldata/appldata_base.c
arch/s390/appldata/appldata_mem.c
arch/s390/appldata/appldata_net_sum.c
arch/s390/appldata/appldata_os.c
arch/s390/crypto/crypt_s390.h
arch/s390/crypto/prng.c
arch/s390/hypfs/inode.c
arch/s390/kernel/Makefile
arch/s390/kernel/binfmt_elf32.c [deleted file]
arch/s390/kernel/compat_ptrace.h
arch/s390/kernel/debug.c
arch/s390/kernel/early.c
arch/s390/kernel/ipl.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/mem_detect.c [new file with mode: 0644]
arch/s390/kernel/process.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/setup.c
arch/s390/kernel/time.c
arch/s390/kernel/topology.c
arch/s390/kernel/vtime.c
arch/s390/mm/init.c
arch/x86/kernel/traps_64.c
block/Kconfig
block/Makefile
block/as-iosched.c
block/blk-core.c
block/blk-integrity.c [new file with mode: 0644]
block/blk-map.c
block/blk-merge.c
block/blk-settings.c
block/blk.h
block/blktrace.c
block/bsg.c
block/cfq-iosched.c
block/cmd-filter.c [new file with mode: 0644]
block/elevator.c
block/genhd.c
block/scsi_ioctl.c
crypto/Kconfig
crypto/Makefile
crypto/ahash.c [new file with mode: 0644]
crypto/api.c
crypto/camellia.c
crypto/crc32c.c
crypto/cryptd.c
crypto/digest.c
crypto/hash.c
crypto/hmac.c
crypto/internal.h
crypto/prng.c [new file with mode: 0644]
crypto/prng.h [new file with mode: 0644]
crypto/ripemd.h [new file with mode: 0644]
crypto/rmd128.c [new file with mode: 0644]
crypto/rmd160.c [new file with mode: 0644]
crypto/rmd256.c [new file with mode: 0644]
crypto/rmd320.c [new file with mode: 0644]
crypto/tcrypt.c
crypto/tcrypt.h
drivers/Makefile
drivers/ata/libata-scsi.c
drivers/block/DAC960.c
drivers/block/aoe/aoecmd.c
drivers/block/paride/pt.c
drivers/block/pktcdvd.c
drivers/block/xen-blkfront.c
drivers/cdrom/cdrom.c
drivers/char/Makefile
drivers/char/drm/Makefile [deleted file]
drivers/char/pcmcia/cm4000_cs.c
drivers/char/pcmcia/cm4040_cs.c
drivers/char/pcmcia/ipwireless/main.c
drivers/crypto/Kconfig
drivers/crypto/Makefile
drivers/crypto/hifn_795x.c
drivers/crypto/ixp4xx_crypto.c [new file with mode: 0644]
drivers/crypto/padlock-aes.c
drivers/crypto/padlock-sha.c
drivers/crypto/talitos.c [new file with mode: 0644]
drivers/crypto/talitos.h [new file with mode: 0644]
drivers/gpu/Makefile [new file with mode: 0644]
drivers/gpu/drm/Kconfig [moved from drivers/char/drm/Kconfig with 100% similarity]
drivers/gpu/drm/Makefile [new file with mode: 0644]
drivers/gpu/drm/README.drm [moved from drivers/char/drm/README.drm with 100% similarity]
drivers/gpu/drm/ati_pcigart.c [moved from drivers/char/drm/ati_pcigart.c with 100% similarity]
drivers/gpu/drm/drm_agpsupport.c [moved from drivers/char/drm/drm_agpsupport.c with 100% similarity]
drivers/gpu/drm/drm_auth.c [moved from drivers/char/drm/drm_auth.c with 100% similarity]
drivers/gpu/drm/drm_bufs.c [moved from drivers/char/drm/drm_bufs.c with 100% similarity]
drivers/gpu/drm/drm_context.c [moved from drivers/char/drm/drm_context.c with 100% similarity]
drivers/gpu/drm/drm_dma.c [moved from drivers/char/drm/drm_dma.c with 100% similarity]
drivers/gpu/drm/drm_drawable.c [moved from drivers/char/drm/drm_drawable.c with 100% similarity]
drivers/gpu/drm/drm_drv.c [moved from drivers/char/drm/drm_drv.c with 100% similarity]
drivers/gpu/drm/drm_fops.c [moved from drivers/char/drm/drm_fops.c with 100% similarity]
drivers/gpu/drm/drm_hashtab.c [moved from drivers/char/drm/drm_hashtab.c with 100% similarity]
drivers/gpu/drm/drm_ioc32.c [moved from drivers/char/drm/drm_ioc32.c with 100% similarity]
drivers/gpu/drm/drm_ioctl.c [moved from drivers/char/drm/drm_ioctl.c with 100% similarity]
drivers/gpu/drm/drm_irq.c [moved from drivers/char/drm/drm_irq.c with 100% similarity]
drivers/gpu/drm/drm_lock.c [moved from drivers/char/drm/drm_lock.c with 100% similarity]
drivers/gpu/drm/drm_memory.c [moved from drivers/char/drm/drm_memory.c with 100% similarity]
drivers/gpu/drm/drm_mm.c [moved from drivers/char/drm/drm_mm.c with 100% similarity]
drivers/gpu/drm/drm_pci.c [moved from drivers/char/drm/drm_pci.c with 100% similarity]
drivers/gpu/drm/drm_proc.c [moved from drivers/char/drm/drm_proc.c with 100% similarity]
drivers/gpu/drm/drm_scatter.c [moved from drivers/char/drm/drm_scatter.c with 100% similarity]
drivers/gpu/drm/drm_sman.c [moved from drivers/char/drm/drm_sman.c with 100% similarity]
drivers/gpu/drm/drm_stub.c [moved from drivers/char/drm/drm_stub.c with 100% similarity]
drivers/gpu/drm/drm_sysfs.c [moved from drivers/char/drm/drm_sysfs.c with 100% similarity]
drivers/gpu/drm/drm_vm.c [moved from drivers/char/drm/drm_vm.c with 100% similarity]
drivers/gpu/drm/i810/Makefile [new file with mode: 0644]
drivers/gpu/drm/i810/i810_dma.c [moved from drivers/char/drm/i810_dma.c with 100% similarity]
drivers/gpu/drm/i810/i810_drv.c [moved from drivers/char/drm/i810_drv.c with 100% similarity]
drivers/gpu/drm/i810/i810_drv.h [moved from drivers/char/drm/i810_drv.h with 100% similarity]
drivers/gpu/drm/i830/Makefile [new file with mode: 0644]
drivers/gpu/drm/i830/i830_dma.c [moved from drivers/char/drm/i830_dma.c with 100% similarity]
drivers/gpu/drm/i830/i830_drv.c [moved from drivers/char/drm/i830_drv.c with 100% similarity]
drivers/gpu/drm/i830/i830_drv.h [moved from drivers/char/drm/i830_drv.h with 100% similarity]
drivers/gpu/drm/i830/i830_irq.c [moved from drivers/char/drm/i830_irq.c with 100% similarity]
drivers/gpu/drm/i915/Makefile [new file with mode: 0644]
drivers/gpu/drm/i915/i915_dma.c [moved from drivers/char/drm/i915_dma.c with 100% similarity]
drivers/gpu/drm/i915/i915_drv.c [moved from drivers/char/drm/i915_drv.c with 100% similarity]
drivers/gpu/drm/i915/i915_drv.h [moved from drivers/char/drm/i915_drv.h with 100% similarity]
drivers/gpu/drm/i915/i915_ioc32.c [moved from drivers/char/drm/i915_ioc32.c with 100% similarity]
drivers/gpu/drm/i915/i915_irq.c [moved from drivers/char/drm/i915_irq.c with 100% similarity]
drivers/gpu/drm/i915/i915_mem.c [moved from drivers/char/drm/i915_mem.c with 100% similarity]
drivers/gpu/drm/mga/Makefile [new file with mode: 0644]
drivers/gpu/drm/mga/mga_dma.c [moved from drivers/char/drm/mga_dma.c with 100% similarity]
drivers/gpu/drm/mga/mga_drv.c [moved from drivers/char/drm/mga_drv.c with 100% similarity]
drivers/gpu/drm/mga/mga_drv.h [moved from drivers/char/drm/mga_drv.h with 100% similarity]
drivers/gpu/drm/mga/mga_ioc32.c [moved from drivers/char/drm/mga_ioc32.c with 100% similarity]
drivers/gpu/drm/mga/mga_irq.c [moved from drivers/char/drm/mga_irq.c with 100% similarity]
drivers/gpu/drm/mga/mga_state.c [moved from drivers/char/drm/mga_state.c with 100% similarity]
drivers/gpu/drm/mga/mga_ucode.h [moved from drivers/char/drm/mga_ucode.h with 100% similarity]
drivers/gpu/drm/mga/mga_warp.c [moved from drivers/char/drm/mga_warp.c with 100% similarity]
drivers/gpu/drm/r128/Makefile [new file with mode: 0644]
drivers/gpu/drm/r128/r128_cce.c [moved from drivers/char/drm/r128_cce.c with 100% similarity]
drivers/gpu/drm/r128/r128_drv.c [moved from drivers/char/drm/r128_drv.c with 100% similarity]
drivers/gpu/drm/r128/r128_drv.h [moved from drivers/char/drm/r128_drv.h with 100% similarity]
drivers/gpu/drm/r128/r128_ioc32.c [moved from drivers/char/drm/r128_ioc32.c with 100% similarity]
drivers/gpu/drm/r128/r128_irq.c [moved from drivers/char/drm/r128_irq.c with 100% similarity]
drivers/gpu/drm/r128/r128_state.c [moved from drivers/char/drm/r128_state.c with 100% similarity]
drivers/gpu/drm/radeon/Makefile [new file with mode: 0644]
drivers/gpu/drm/radeon/r300_cmdbuf.c [moved from drivers/char/drm/r300_cmdbuf.c with 100% similarity]
drivers/gpu/drm/radeon/r300_reg.h [moved from drivers/char/drm/r300_reg.h with 100% similarity]
drivers/gpu/drm/radeon/radeon_cp.c [moved from drivers/char/drm/radeon_cp.c with 100% similarity]
drivers/gpu/drm/radeon/radeon_drv.c [moved from drivers/char/drm/radeon_drv.c with 100% similarity]
drivers/gpu/drm/radeon/radeon_drv.h [moved from drivers/char/drm/radeon_drv.h with 100% similarity]
drivers/gpu/drm/radeon/radeon_ioc32.c [moved from drivers/char/drm/radeon_ioc32.c with 100% similarity]
drivers/gpu/drm/radeon/radeon_irq.c [moved from drivers/char/drm/radeon_irq.c with 100% similarity]
drivers/gpu/drm/radeon/radeon_mem.c [moved from drivers/char/drm/radeon_mem.c with 100% similarity]
drivers/gpu/drm/radeon/radeon_microcode.h [moved from drivers/char/drm/radeon_microcode.h with 100% similarity]
drivers/gpu/drm/radeon/radeon_state.c [moved from drivers/char/drm/radeon_state.c with 100% similarity]
drivers/gpu/drm/savage/Makefile [new file with mode: 0644]
drivers/gpu/drm/savage/savage_bci.c [moved from drivers/char/drm/savage_bci.c with 100% similarity]
drivers/gpu/drm/savage/savage_drv.c [moved from drivers/char/drm/savage_drv.c with 100% similarity]
drivers/gpu/drm/savage/savage_drv.h [moved from drivers/char/drm/savage_drv.h with 100% similarity]
drivers/gpu/drm/savage/savage_state.c [moved from drivers/char/drm/savage_state.c with 100% similarity]
drivers/gpu/drm/sis/Makefile [new file with mode: 0644]
drivers/gpu/drm/sis/sis_drv.c [moved from drivers/char/drm/sis_drv.c with 100% similarity]
drivers/gpu/drm/sis/sis_drv.h [moved from drivers/char/drm/sis_drv.h with 100% similarity]
drivers/gpu/drm/sis/sis_mm.c [moved from drivers/char/drm/sis_mm.c with 100% similarity]
drivers/gpu/drm/tdfx/Makefile [new file with mode: 0644]
drivers/gpu/drm/tdfx/tdfx_drv.c [moved from drivers/char/drm/tdfx_drv.c with 100% similarity]
drivers/gpu/drm/tdfx/tdfx_drv.h [moved from drivers/char/drm/tdfx_drv.h with 100% similarity]
drivers/gpu/drm/via/Makefile [new file with mode: 0644]
drivers/gpu/drm/via/via_3d_reg.h [moved from drivers/char/drm/via_3d_reg.h with 100% similarity]
drivers/gpu/drm/via/via_dma.c [moved from drivers/char/drm/via_dma.c with 100% similarity]
drivers/gpu/drm/via/via_dmablit.c [moved from drivers/char/drm/via_dmablit.c with 100% similarity]
drivers/gpu/drm/via/via_dmablit.h [moved from drivers/char/drm/via_dmablit.h with 100% similarity]
drivers/gpu/drm/via/via_drv.c [moved from drivers/char/drm/via_drv.c with 100% similarity]
drivers/gpu/drm/via/via_drv.h [moved from drivers/char/drm/via_drv.h with 100% similarity]
drivers/gpu/drm/via/via_irq.c [moved from drivers/char/drm/via_irq.c with 100% similarity]
drivers/gpu/drm/via/via_map.c [moved from drivers/char/drm/via_map.c with 100% similarity]
drivers/gpu/drm/via/via_mm.c [moved from drivers/char/drm/via_mm.c with 100% similarity]
drivers/gpu/drm/via/via_verifier.c [moved from drivers/char/drm/via_verifier.c with 100% similarity]
drivers/gpu/drm/via/via_verifier.h [moved from drivers/char/drm/via_verifier.h with 100% similarity]
drivers/gpu/drm/via/via_video.c [moved from drivers/char/drm/via_video.c with 100% similarity]
drivers/ide/legacy/ide-cs.c
drivers/md/linear.c
drivers/md/raid0.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/misc/atmel_pwm.c
drivers/mtd/ftl.c
drivers/mtd/maps/pcmciamtd.c
drivers/net/macb.c
drivers/net/xen-netfront.c
drivers/pcmcia/Kconfig
drivers/pcmcia/Makefile
drivers/pcmcia/au1000_generic.h
drivers/pcmcia/au1000_pb1x00.c
drivers/pcmcia/au1000_xxs1500.c
drivers/pcmcia/bfin_cf_pcmcia.c [new file with mode: 0644]
drivers/pcmcia/cardbus.c
drivers/pcmcia/cistpl.c
drivers/pcmcia/cs.c
drivers/pcmcia/cs_internal.h
drivers/pcmcia/ds.c
drivers/pcmcia/hd64465_ss.c
drivers/pcmcia/i82092.c
drivers/pcmcia/i82092aa.h
drivers/pcmcia/i82365.c
drivers/pcmcia/m8xx_pcmcia.c
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/pxa2xx_base.c
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/rsrc_nonstatic.c
drivers/pcmcia/soc_common.h
drivers/pcmcia/socket_sysfs.c
drivers/pcmcia/ti113x.h
drivers/rtc/rtc-at32ap700x.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dcssblk.c
drivers/s390/block/xpram.c
drivers/s390/char/con3215.c
drivers/s390/char/con3270.c
drivers/s390/char/fs3270.c
drivers/s390/char/monreader.c
drivers/s390/char/raw3270.c
drivers/s390/char/sclp.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/sclp_con.c
drivers/s390/char/sclp_config.c
drivers/s390/char/sclp_cpi_sys.c
drivers/s390/char/sclp_quiesce.c
drivers/s390/char/sclp_rw.c
drivers/s390/char/sclp_sdias.c
drivers/s390/char/sclp_tty.c
drivers/s390/char/sclp_tty.h
drivers/s390/char/sclp_vt220.c
drivers/s390/char/tape_34xx.c
drivers/s390/char/tape_3590.c
drivers/s390/char/tape_core.c
drivers/s390/char/tty3270.c
drivers/s390/char/vmcp.c
drivers/s390/char/vmlogrdr.c
drivers/s390/char/vmur.c
drivers/s390/char/vmwatchdog.c
drivers/s390/char/zcore.c
drivers/s390/cio/Makefile
drivers/s390/cio/airq.c
drivers/s390/cio/chp.c
drivers/s390/cio/chp.h
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/chsc_sch.c [new file with mode: 0644]
drivers/s390/cio/chsc_sch.h [new file with mode: 0644]
drivers/s390/cio/cio.c
drivers/s390/cio/cio.h
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_id.c
drivers/s390/cio/device_ops.c
drivers/s390/cio/device_pgid.c
drivers/s390/cio/device_status.c
drivers/s390/cio/fcx.c [new file with mode: 0644]
drivers/s390/cio/idset.h
drivers/s390/cio/io_sch.h
drivers/s390/cio/ioasm.h
drivers/s390/cio/isc.c [new file with mode: 0644]
drivers/s390/cio/itcw.c [new file with mode: 0644]
drivers/s390/cio/qdio.c
drivers/s390/cio/qdio.h
drivers/s390/cio/scsw.c [new file with mode: 0644]
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_api.h
drivers/s390/crypto/zcrypt_cex2a.c
drivers/s390/crypto/zcrypt_error.h
drivers/s390/crypto/zcrypt_pcica.c
drivers/s390/crypto/zcrypt_pcicc.c
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/net/claw.c
drivers/s390/net/ctcm_fsms.c
drivers/s390/net/ctcm_main.c
drivers/s390/net/cu3088.c
drivers/s390/net/cu3088.h
drivers/s390/net/lcs.c
drivers/s390/net/netiucv.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/smsgiucv.c
drivers/s390/s390mach.c
drivers/s390/s390mach.h
drivers/scsi/sg.c
drivers/scsi/sr.c
drivers/serial/atmel_serial.c
drivers/video/Kconfig
drivers/xen/xenbus/xenbus_client.c
drivers/xen/xenbus/xenbus_xs.c
fs/Makefile
fs/bio-integrity.c [new file with mode: 0644]
fs/bio.c
fs/namespace.c
fs/proc/base.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/ramfs/file-mmu.c
fs/ramfs/file-nommu.c
fs/splice.c
include/Kbuild
include/asm-avr32/arch-at32ap/board.h
include/asm-avr32/arch-at32ap/init.h
include/asm-avr32/arch-at32ap/pm.h
include/asm-avr32/arch-at32ap/sram.h [new file with mode: 0644]
include/asm-avr32/mmu_context.h
include/asm-avr32/pci.h
include/asm-avr32/pgalloc.h
include/asm-avr32/pgtable.h
include/asm-avr32/thread_info.h
include/asm-avr32/tlbflush.h
include/asm-mips/mach-au1x00/au1xxx_psc.h
include/asm-s390/Kbuild
include/asm-s390/airq.h
include/asm-s390/ccwdev.h
include/asm-s390/chpid.h
include/asm-s390/chsc.h [new file with mode: 0644]
include/asm-s390/cio.h
include/asm-s390/elf.h
include/asm-s390/etr.h
include/asm-s390/fcx.h [new file with mode: 0644]
include/asm-s390/ipl.h
include/asm-s390/isc.h [new file with mode: 0644]
include/asm-s390/itcw.h [new file with mode: 0644]
include/asm-s390/pgtable.h
include/asm-s390/processor.h
include/asm-s390/ptrace.h
include/asm-s390/schid.h [moved from drivers/s390/cio/schid.h with 65% similarity]
include/asm-s390/sclp.h
include/asm-s390/setup.h
include/asm-s390/sparsemem.h
include/asm-s390/timer.h
include/asm-s390/zcrypt.h
include/crypto/hash.h [new file with mode: 0644]
include/crypto/internal/hash.h [new file with mode: 0644]
include/drm/Kbuild [new file with mode: 0644]
include/drm/drm.h [moved from drivers/char/drm/drm.h with 100% similarity]
include/drm/drmP.h [moved from drivers/char/drm/drmP.h with 100% similarity]
include/drm/drm_core.h [moved from drivers/char/drm/drm_core.h with 100% similarity]
include/drm/drm_hashtab.h [moved from drivers/char/drm/drm_hashtab.h with 100% similarity]
include/drm/drm_memory.h [moved from drivers/char/drm/drm_memory.h with 100% similarity]
include/drm/drm_memory_debug.h [moved from drivers/char/drm/drm_memory_debug.h with 100% similarity]
include/drm/drm_os_linux.h [moved from drivers/char/drm/drm_os_linux.h with 100% similarity]
include/drm/drm_pciids.h [moved from drivers/char/drm/drm_pciids.h with 100% similarity]
include/drm/drm_sarea.h [moved from drivers/char/drm/drm_sarea.h with 100% similarity]
include/drm/drm_sman.h [moved from drivers/char/drm/drm_sman.h with 100% similarity]
include/drm/i810_drm.h [moved from drivers/char/drm/i810_drm.h with 100% similarity]
include/drm/i830_drm.h [moved from drivers/char/drm/i830_drm.h with 100% similarity]
include/drm/i915_drm.h [moved from drivers/char/drm/i915_drm.h with 100% similarity]
include/drm/mga_drm.h [moved from drivers/char/drm/mga_drm.h with 100% similarity]
include/drm/r128_drm.h [moved from drivers/char/drm/r128_drm.h with 100% similarity]
include/drm/radeon_drm.h [moved from drivers/char/drm/radeon_drm.h with 100% similarity]
include/drm/savage_drm.h [moved from drivers/char/drm/savage_drm.h with 100% similarity]
include/drm/sis_drm.h [moved from drivers/char/drm/sis_drm.h with 100% similarity]
include/drm/via_drm.h [moved from drivers/char/drm/via_drm.h with 100% similarity]
include/linux/bio.h
include/linux/blkdev.h
include/linux/blktrace_api.h
include/linux/crypto.h
include/linux/genhd.h
include/linux/iocontext.h
include/linux/mod_devicetable.h
include/linux/ptrace.h
include/linux/security.h
include/pcmcia/bulkmem.h [deleted file]
include/pcmcia/cistpl.h
include/pcmcia/cs.h
include/pcmcia/cs_types.h
include/pcmcia/ds.h
include/pcmcia/ss.h
include/pcmcia/version.h [deleted file]
include/sound/ad1843.h [new file with mode: 0644]
include/sound/control.h
include/sound/core.h
include/sound/cs4231-regs.h
include/sound/cs4231.h
include/sound/emu10k1.h
include/sound/seq_kernel.h
include/sound/soc-dapm.h
include/sound/soc.h
include/sound/uda1341.h
include/sound/version.h
kernel/exit.c
kernel/fork.c
kernel/ptrace.c
mm/Kconfig
mm/slub.c
net/iucv/af_iucv.c
net/iucv/iucv.c
scripts/mod/file2alias.c
security/Kconfig
security/Makefile
security/capability.c
security/commoncap.c
security/dummy.c [deleted file]
security/root_plug.c
security/security.c
security/selinux/hooks.c
security/selinux/include/audit.h
security/selinux/include/avc.h
security/selinux/include/objsec.h
security/selinux/include/security.h
security/selinux/netnode.c
security/selinux/netport.c
security/selinux/selinuxfs.c
security/selinux/ss/avtab.c
security/selinux/ss/context.h
security/selinux/ss/mls.c
security/selinux/ss/mls.h
security/selinux/ss/policydb.c
security/selinux/ss/services.c
security/selinux/ss/sidtab.c
security/selinux/ss/sidtab.h
security/smack/smack_lsm.c
sound/Kconfig
sound/aoa/Kconfig
sound/aoa/codecs/Kconfig
sound/aoa/fabrics/Kconfig
sound/aoa/soundbus/Kconfig
sound/arm/Kconfig
sound/arm/sa11xx-uda1341.c
sound/core/Kconfig
sound/core/control.c
sound/core/init.c
sound/core/memalloc.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_device.c
sound/core/sound.c
sound/core/timer.c
sound/drivers/Kconfig
sound/drivers/vx/vx_hwdep.c
sound/i2c/cs8427.c
sound/i2c/l3/uda1341.c
sound/isa/Kconfig
sound/isa/cs423x/cs4231_lib.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/Makefile
sound/isa/wavefront/wavefront_synth.c
sound/mips/Kconfig
sound/mips/Makefile
sound/mips/ad1843.c [new file with mode: 0644]
sound/mips/hal2.c [new file with mode: 0644]
sound/mips/hal2.h [new file with mode: 0644]
sound/mips/sgio2audio.c [new file with mode: 0644]
sound/oss/Kconfig
sound/oss/dmasound/dmasound_core.c
sound/oss/dmasound/dmasound_paula.c
sound/oss/dmasound/dmasound_q40.c
sound/oss/msnd.c
sound/oss/msnd.h
sound/oss/msnd_classic.h
sound/oss/msnd_pinnacle.c
sound/oss/msnd_pinnacle.h
sound/parisc/Kconfig
sound/pci/Kconfig
sound/pci/Makefile
sound/pci/ac97/Makefile
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_patch.c
sound/pci/ak4531_codec.c [moved from sound/pci/ac97/ak4531_codec.c with 96% similarity]
sound/pci/au88x0/au88x0_game.c
sound/pci/azt3328.c
sound/pci/azt3328.h
sound/pci/ca0106/ca0106_main.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/memory.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_hwdep.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_proc.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/envy24ht.h
sound/pci/ice1712/ice1712.h
sound/pci/ice1712/ice1724.c
sound/pci/maestro3.c
sound/pci/nm256/nm256.c
sound/pci/oxygen/hifier.c
sound/pci/oxygen/oxygen.c
sound/pci/oxygen/oxygen.h
sound/pci/oxygen/oxygen_io.c
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/oxygen_pcm.c
sound/pci/oxygen/virtuoso.c
sound/pci/pcxhr/pcxhr.c
sound/pci/pcxhr/pcxhr_core.c
sound/pci/trident/trident_main.c
sound/pci/trident/trident_memory.c
sound/pci/via82xx.c
sound/pci/ymfpci/ymfpci_main.c
sound/pcmcia/Kconfig
sound/pcmcia/vx/vxp_ops.c
sound/ppc/Kconfig
sound/ppc/daca.c
sound/ppc/tumbler.c
sound/sh/Kconfig
sound/soc/Kconfig
sound/soc/Makefile
sound/soc/at32/Kconfig [new file with mode: 0644]
sound/soc/at32/Makefile [new file with mode: 0644]
sound/soc/at32/at32-pcm.c [new file with mode: 0644]
sound/soc/at32/at32-pcm.h [new file with mode: 0644]
sound/soc/at32/at32-ssc.c [new file with mode: 0644]
sound/soc/at32/at32-ssc.h [new file with mode: 0644]
sound/soc/at32/playpaq_wm8510.c [new file with mode: 0644]
sound/soc/at91/Kconfig
sound/soc/at91/at91-pcm.c
sound/soc/at91/at91-ssc.c
sound/soc/at91/at91-ssc.h
sound/soc/at91/eti_b1_wm8731.c
sound/soc/au1x/Kconfig [new file with mode: 0644]
sound/soc/au1x/Makefile [new file with mode: 0644]
sound/soc/au1x/dbdma2.c [new file with mode: 0644]
sound/soc/au1x/psc-ac97.c [new file with mode: 0644]
sound/soc/au1x/psc-i2s.c [new file with mode: 0644]
sound/soc/au1x/psc.h [new file with mode: 0644]
sound/soc/au1x/sample-ac97.c [new file with mode: 0644]
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ac97.c
sound/soc/codecs/ac97.h
sound/soc/codecs/ak4535.c [new file with mode: 0644]
sound/soc/codecs/ak4535.h [new file with mode: 0644]
sound/soc/codecs/cs4270.c
sound/soc/codecs/cs4270.h
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320aic3x.h
sound/soc/codecs/uda1380.c [new file with mode: 0644]
sound/soc/codecs/uda1380.h [new file with mode: 0644]
sound/soc/codecs/wm8510.c [new file with mode: 0644]
sound/soc/codecs/wm8510.h [new file with mode: 0644]
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8731.h
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8750.h
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8753.h
sound/soc/codecs/wm8990.c [new file with mode: 0644]
sound/soc/codecs/wm8990.h [new file with mode: 0644]
sound/soc/codecs/wm9712.c
sound/soc/codecs/wm9712.h
sound/soc/codecs/wm9713.c
sound/soc/codecs/wm9713.h
sound/soc/davinci/Kconfig
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-i2s.h
sound/soc/davinci/davinci-pcm.c
sound/soc/fsl/Kconfig
sound/soc/fsl/fsl_dma.c
sound/soc/fsl/fsl_dma.h
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/fsl_ssi.h
sound/soc/fsl/mpc8610_hpcd.c
sound/soc/omap/Kconfig
sound/soc/omap/n810.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.h
sound/soc/omap/omap-pcm.c
sound/soc/pxa/Kconfig
sound/soc/pxa/Makefile
sound/soc/pxa/corgi.c
sound/soc/pxa/em-x270.c [new file with mode: 0644]
sound/soc/pxa/poodle.c
sound/soc/pxa/pxa2xx-ac97.c
sound/soc/pxa/pxa2xx-ac97.h
sound/soc/pxa/pxa2xx-i2s.c
sound/soc/pxa/pxa2xx-i2s.h
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/pxa/spitz.c
sound/soc/pxa/tosa.c
sound/soc/s3c24xx/Kconfig
sound/soc/s3c24xx/neo1973_wm8753.c
sound/soc/s3c24xx/s3c2412-i2s.c
sound/soc/s3c24xx/s3c2412-i2s.h
sound/soc/s3c24xx/s3c2443-ac97.c
sound/soc/s3c24xx/s3c24xx-ac97.h
sound/soc/s3c24xx/s3c24xx-i2s.c
sound/soc/s3c24xx/s3c24xx-i2s.h
sound/soc/s3c24xx/s3c24xx-pcm.c
sound/soc/s3c24xx/smdk2443_wm9710.c
sound/soc/sh/Kconfig
sound/soc/sh/dma-sh7760.c
sound/soc/sh/hac.c
sound/soc/sh/sh7760-ac97.c
sound/soc/sh/ssi.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/sparc/Kconfig
sound/sparc/dbri.c
sound/spi/Kconfig
sound/usb/Kconfig
sound/usb/caiaq/caiaq-audio.c
sound/usb/caiaq/caiaq-device.c
sound/usb/caiaq/caiaq-device.h
sound/usb/usbaudio.c
sound/usb/usbquirks.h

index 4bd9ea5..44f52a4 100644 (file)
@@ -26,3 +26,37 @@ Description:
                I/O statistics of partition <part>. The format is the
                same as the above-written /sys/block/<disk>/stat
                format.
+
+
+What:          /sys/block/<disk>/integrity/format
+Date:          June 2008
+Contact:       Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+               Metadata format for integrity capable block device.
+               E.g. T10-DIF-TYPE1-CRC.
+
+
+What:          /sys/block/<disk>/integrity/read_verify
+Date:          June 2008
+Contact:       Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+               Indicates whether the block layer should verify the
+               integrity of read requests serviced by devices that
+               support sending integrity metadata.
+
+
+What:          /sys/block/<disk>/integrity/tag_size
+Date:          June 2008
+Contact:       Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+               Number of bytes of integrity tag space available per
+               512 bytes of data.
+
+
+What:          /sys/block/<disk>/integrity/write_generate
+Date:          June 2008
+Contact:       Martin K. Petersen <martin.petersen@oracle.com>
+Description:
+               Indicates whether the block layer should automatically
+               generate checksums for write requests bound for
+               devices that support receiving integrity metadata.
diff --git a/Documentation/ABI/testing/sysfs-bus-css b/Documentation/ABI/testing/sysfs-bus-css
new file mode 100644 (file)
index 0000000..b585ec2
--- /dev/null
@@ -0,0 +1,35 @@
+What:          /sys/bus/css/devices/.../type
+Date:          March 2008
+Contact:       Cornelia Huck <cornelia.huck@de.ibm.com>
+               linux-s390@vger.kernel.org
+Description:   Contains the subchannel type, as reported by the hardware.
+               This attribute is present for all subchannel types.
+
+What:          /sys/bus/css/devices/.../modalias
+Date:          March 2008
+Contact:       Cornelia Huck <cornelia.huck@de.ibm.com>
+               linux-s390@vger.kernel.org
+Description:   Contains the module alias as reported with uevents.
+               It is of the format css:t<type> and present for all
+               subchannel types.
+
+What:          /sys/bus/css/drivers/io_subchannel/.../chpids
+Date:          December 2002
+Contact:       Cornelia Huck <cornelia.huck@de.ibm.com>
+               linux-s390@vger.kernel.org
+Description:   Contains the ids of the channel paths used by this
+               subchannel, as reported by the channel subsystem
+               during subchannel recognition.
+               Note: This is an I/O-subchannel specific attribute.
+Users:         s390-tools, HAL
+
+What:          /sys/bus/css/drivers/io_subchannel/.../pimpampom
+Date:          December 2002
+Contact:       Cornelia Huck <cornelia.huck@de.ibm.com>
+               linux-s390@vger.kernel.org
+Description:   Contains the PIM/PAM/POM values, as reported by the
+               channel subsystem when last queried by the common I/O
+               layer (this implies that this attribute is not neccessarily
+               in sync with the values current in the channel subsystem).
+               Note: This is an I/O-subchannel specific attribute.
+Users:         s390-tools, HAL
diff --git a/Documentation/block/data-integrity.txt b/Documentation/block/data-integrity.txt
new file mode 100644 (file)
index 0000000..e9dc8d8
--- /dev/null
@@ -0,0 +1,327 @@
+----------------------------------------------------------------------
+1. INTRODUCTION
+
+Modern filesystems feature checksumming of data and metadata to
+protect against data corruption.  However, the detection of the
+corruption is done at read time which could potentially be months
+after the data was written.  At that point the original data that the
+application tried to write is most likely lost.
+
+The solution is to ensure that the disk is actually storing what the
+application meant it to.  Recent additions to both the SCSI family
+protocols (SBC Data Integrity Field, SCC protection proposal) as well
+as SATA/T13 (External Path Protection) try to remedy this by adding
+support for appending integrity metadata to an I/O.  The integrity
+metadata (or protection information in SCSI terminology) includes a
+checksum for each sector as well as an incrementing counter that
+ensures the individual sectors are written in the right order.  And
+for some protection schemes also that the I/O is written to the right
+place on disk.
+
+Current storage controllers and devices implement various protective
+measures, for instance checksumming and scrubbing.  But these
+technologies are working in their own isolated domains or at best
+between adjacent nodes in the I/O path.  The interesting thing about
+DIF and the other integrity extensions is that the protection format
+is well defined and every node in the I/O path can verify the
+integrity of the I/O and reject it if corruption is detected.  This
+allows not only corruption prevention but also isolation of the point
+of failure.
+
+----------------------------------------------------------------------
+2. THE DATA INTEGRITY EXTENSIONS
+
+As written, the protocol extensions only protect the path between
+controller and storage device.  However, many controllers actually
+allow the operating system to interact with the integrity metadata
+(IMD).  We have been working with several FC/SAS HBA vendors to enable
+the protection information to be transferred to and from their
+controllers.
+
+The SCSI Data Integrity Field works by appending 8 bytes of protection
+information to each sector.  The data + integrity metadata is stored
+in 520 byte sectors on disk.  Data + IMD are interleaved when
+transferred between the controller and target.  The T13 proposal is
+similar.
+
+Because it is highly inconvenient for operating systems to deal with
+520 (and 4104) byte sectors, we approached several HBA vendors and
+encouraged them to allow separation of the data and integrity metadata
+scatter-gather lists.
+
+The controller will interleave the buffers on write and split them on
+read.  This means that the Linux can DMA the data buffers to and from
+host memory without changes to the page cache.
+
+Also, the 16-bit CRC checksum mandated by both the SCSI and SATA specs
+is somewhat heavy to compute in software.  Benchmarks found that
+calculating this checksum had a significant impact on system
+performance for a number of workloads.  Some controllers allow a
+lighter-weight checksum to be used when interfacing with the operating
+system.  Emulex, for instance, supports the TCP/IP checksum instead.
+The IP checksum received from the OS is converted to the 16-bit CRC
+when writing and vice versa.  This allows the integrity metadata to be
+generated by Linux or the application at very low cost (comparable to
+software RAID5).
+
+The IP checksum is weaker than the CRC in terms of detecting bit
+errors.  However, the strength is really in the separation of the data
+buffers and the integrity metadata.  These two distinct buffers much
+match up for an I/O to complete.
+
+The separation of the data and integrity metadata buffers as well as
+the choice in checksums is referred to as the Data Integrity
+Extensions.  As these extensions are outside the scope of the protocol
+bodies (T10, T13), Oracle and its partners are trying to standardize
+them within the Storage Networking Industry Association.
+
+----------------------------------------------------------------------
+3. KERNEL CHANGES
+
+The data integrity framework in Linux enables protection information
+to be pinned to I/Os and sent to/received from controllers that
+support it.
+
+The advantage to the integrity extensions in SCSI and SATA is that
+they enable us to protect the entire path from application to storage
+device.  However, at the same time this is also the biggest
+disadvantage. It means that the protection information must be in a
+format that can be understood by the disk.
+
+Generally Linux/POSIX applications are agnostic to the intricacies of
+the storage devices they are accessing.  The virtual filesystem switch
+and the block layer make things like hardware sector size and
+transport protocols completely transparent to the application.
+
+However, this level of detail is required when preparing the
+protection information to send to a disk.  Consequently, the very
+concept of an end-to-end protection scheme is a layering violation.
+It is completely unreasonable for an application to be aware whether
+it is accessing a SCSI or SATA disk.
+
+The data integrity support implemented in Linux attempts to hide this
+from the application.  As far as the application (and to some extent
+the kernel) is concerned, the integrity metadata is opaque information
+that's attached to the I/O.
+
+The current implementation allows the block layer to automatically
+generate the protection information for any I/O.  Eventually the
+intent is to move the integrity metadata calculation to userspace for
+user data.  Metadata and other I/O that originates within the kernel
+will still use the automatic generation interface.
+
+Some storage devices allow each hardware sector to be tagged with a
+16-bit value.  The owner of this tag space is the owner of the block
+device.  I.e. the filesystem in most cases.  The filesystem can use
+this extra space to tag sectors as they see fit.  Because the tag
+space is limited, the block interface allows tagging bigger chunks by
+way of interleaving.  This way, 8*16 bits of information can be
+attached to a typical 4KB filesystem block.
+
+This also means that applications such as fsck and mkfs will need
+access to manipulate the tags from user space.  A passthrough
+interface for this is being worked on.
+
+
+----------------------------------------------------------------------
+4. BLOCK LAYER IMPLEMENTATION DETAILS
+
+4.1 BIO
+
+The data integrity patches add a new field to struct bio when
+CONFIG_BLK_DEV_INTEGRITY is enabled.  bio->bi_integrity is a pointer
+to a struct bip which contains the bio integrity payload.  Essentially
+a bip is a trimmed down struct bio which holds a bio_vec containing
+the integrity metadata and the required housekeeping information (bvec
+pool, vector count, etc.)
+
+A kernel subsystem can enable data integrity protection on a bio by
+calling bio_integrity_alloc(bio).  This will allocate and attach the
+bip to the bio.
+
+Individual pages containing integrity metadata can subsequently be
+attached using bio_integrity_add_page().
+
+bio_free() will automatically free the bip.
+
+
+4.2 BLOCK DEVICE
+
+Because the format of the protection data is tied to the physical
+disk, each block device has been extended with a block integrity
+profile (struct blk_integrity).  This optional profile is registered
+with the block layer using blk_integrity_register().
+
+The profile contains callback functions for generating and verifying
+the protection data, as well as getting and setting application tags.
+The profile also contains a few constants to aid in completing,
+merging and splitting the integrity metadata.
+
+Layered block devices will need to pick a profile that's appropriate
+for all subdevices.  blk_integrity_compare() can help with that.  DM
+and MD linear, RAID0 and RAID1 are currently supported.  RAID4/5/6
+will require extra work due to the application tag.
+
+
+----------------------------------------------------------------------
+5.0 BLOCK LAYER INTEGRITY API
+
+5.1 NORMAL FILESYSTEM
+
+    The normal filesystem is unaware that the underlying block device
+    is capable of sending/receiving integrity metadata.  The IMD will
+    be automatically generated by the block layer at submit_bio() time
+    in case of a WRITE.  A READ request will cause the I/O integrity
+    to be verified upon completion.
+
+    IMD generation and verification can be toggled using the
+
+      /sys/block/<bdev>/integrity/write_generate
+
+    and
+
+      /sys/block/<bdev>/integrity/read_verify
+
+    flags.
+
+
+5.2 INTEGRITY-AWARE FILESYSTEM
+
+    A filesystem that is integrity-aware can prepare I/Os with IMD
+    attached.  It can also use the application tag space if this is
+    supported by the block device.
+
+
+    int bdev_integrity_enabled(block_device, int rw);
+
+      bdev_integrity_enabled() will return 1 if the block device
+      supports integrity metadata transfer for the data direction
+      specified in 'rw'.
+
+      bdev_integrity_enabled() honors the write_generate and
+      read_verify flags in sysfs and will respond accordingly.
+
+
+    int bio_integrity_prep(bio);
+
+      To generate IMD for WRITE and to set up buffers for READ, the
+      filesystem must call bio_integrity_prep(bio).
+
+      Prior to calling this function, the bio data direction and start
+      sector must be set, and the bio should have all data pages
+      added.  It is up to the caller to ensure that the bio does not
+      change while I/O is in progress.
+
+      bio_integrity_prep() should only be called if
+      bio_integrity_enabled() returned 1.
+
+
+    int bio_integrity_tag_size(bio);
+
+      If the filesystem wants to use the application tag space it will
+      first have to find out how much storage space is available.
+      Because tag space is generally limited (usually 2 bytes per
+      sector regardless of sector size), the integrity framework
+      supports interleaving the information between the sectors in an
+      I/O.
+
+      Filesystems can call bio_integrity_tag_size(bio) to find out how
+      many bytes of storage are available for that particular bio.
+
+      Another option is bdev_get_tag_size(block_device) which will
+      return the number of available bytes per hardware sector.
+
+
+    int bio_integrity_set_tag(bio, void *tag_buf, len);
+
+      After a successful return from bio_integrity_prep(),
+      bio_integrity_set_tag() can be used to attach an opaque tag
+      buffer to a bio.  Obviously this only makes sense if the I/O is
+      a WRITE.
+
+
+    int bio_integrity_get_tag(bio, void *tag_buf, len);
+
+      Similarly, at READ I/O completion time the filesystem can
+      retrieve the tag buffer using bio_integrity_get_tag().
+
+
+6.3 PASSING EXISTING INTEGRITY METADATA
+
+    Filesystems that either generate their own integrity metadata or
+    are capable of transferring IMD from user space can use the
+    following calls:
+
+
+    struct bip * bio_integrity_alloc(bio, gfp_mask, nr_pages);
+
+      Allocates the bio integrity payload and hangs it off of the bio.
+      nr_pages indicate how many pages of protection data need to be
+      stored in the integrity bio_vec list (similar to bio_alloc()).
+
+      The integrity payload will be freed at bio_free() time.
+
+
+    int bio_integrity_add_page(bio, page, len, offset);
+
+      Attaches a page containing integrity metadata to an existing
+      bio.  The bio must have an existing bip,
+      i.e. bio_integrity_alloc() must have been called.  For a WRITE,
+      the integrity metadata in the pages must be in a format
+      understood by the target device with the notable exception that
+      the sector numbers will be remapped as the request traverses the
+      I/O stack.  This implies that the pages added using this call
+      will be modified during I/O!  The first reference tag in the
+      integrity metadata must have a value of bip->bip_sector.
+
+      Pages can be added using bio_integrity_add_page() as long as
+      there is room in the bip bio_vec array (nr_pages).
+
+      Upon completion of a READ operation, the attached pages will
+      contain the integrity metadata received from the storage device.
+      It is up to the receiver to process them and verify data
+      integrity upon completion.
+
+
+6.4 REGISTERING A BLOCK DEVICE AS CAPABLE OF EXCHANGING INTEGRITY
+    METADATA
+
+    To enable integrity exchange on a block device the gendisk must be
+    registered as capable:
+
+    int blk_integrity_register(gendisk, blk_integrity);
+
+      The blk_integrity struct is a template and should contain the
+      following:
+
+        static struct blk_integrity my_profile = {
+            .name                   = "STANDARDSBODY-TYPE-VARIANT-CSUM",
+            .generate_fn            = my_generate_fn,
+                   .verify_fn              = my_verify_fn,
+                   .get_tag_fn             = my_get_tag_fn,
+                   .set_tag_fn             = my_set_tag_fn,
+           .tuple_size             = sizeof(struct my_tuple_size),
+           .tag_size               = <tag bytes per hw sector>,
+        };
+
+      'name' is a text string which will be visible in sysfs.  This is
+      part of the userland API so chose it carefully and never change
+      it.  The format is standards body-type-variant.
+      E.g. T10-DIF-TYPE1-IP or T13-EPP-0-CRC.
+
+      'generate_fn' generates appropriate integrity metadata (for WRITE).
+
+      'verify_fn' verifies that the data buffer matches the integrity
+      metadata.
+
+      'tuple_size' must be set to match the size of the integrity
+      metadata per sector.  I.e. 8 for DIF and EPP.
+
+      'tag_size' must be set to identify how many bytes of tag space
+      are available per hardware sector.  For DIF this is either 2 or
+      0 depending on the value of the Control Mode Page ATO bit.
+
+      See 6.2 for a description of get_tag_fn and set_tag_fn.
+
+----------------------------------------------------------------------
+2007-12-24 Martin K. Petersen <martin.petersen@oracle.com>
index 240ce7a..3bb5f46 100644 (file)
@@ -117,6 +117,7 @@ Code        Seq#    Include File            Comments
                                        <mailto:natalia@nikhefk.nikhef.nl>
 'c'    00-7F   linux/comstats.h        conflict!
 'c'    00-7F   linux/coda.h            conflict!
+'c'    80-9F   asm-s390/chsc.h
 'd'    00-FF   linux/char/drm/drm/h    conflict!
 'd'    00-DF   linux/video_decoder.h   conflict!
 'd'    F0-FF   linux/digi1.h
index 0bbee38..72aff61 100644 (file)
@@ -753,8 +753,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
     [Multiple options for each card instance]
     model      - force the model name
-    position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
+    position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
     probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
+    bdl_pos_adj        - Specifies the DMA IRQ timing delay in samples.
+               Passing -1 will make the driver to choose the appropriate
+               value based on the controller chip.
     
     [Single (global) options]
     single_cmd  - Use single immediate commands to communicate with
@@ -845,7 +848,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
        ALC269
          basic         Basic preset
 
-       ALC662
+       ALC662/663
          3stack-dig    3-stack (2-channel) with SPDIF
          3stack-6ch     3-stack (6-channel)
          3stack-6ch-dig 3-stack (6-channel) with SPDIF
@@ -853,6 +856,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
          lenovo-101e    Lenovo laptop
          eeepc-p701    ASUS Eeepc P701
          eeepc-ep20    ASUS Eeepc EP20
+         m51va         ASUS M51VA
+         g71v          ASUS G71V
+         h13           ASUS H13
+         g50v          ASUS G50V
          auto          auto-config reading BIOS (default)
 
        ALC882/885
@@ -1091,7 +1098,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     This occurs when the access to non-existing or non-working codec slot
     (likely a modem one) causes a stall of the communication via HD-audio
     bus.  You can see which codec slots are probed by enabling
-    CONFIG_SND_DEBUG_DETECT, or simply from the file name of the codec
+    CONFIG_SND_DEBUG_VERBOSE, or simply from the file name of the codec
     proc files.  Then limit the slots to probe by probe_mask option.
     For example, probe_mask=1 means to probe only the first slot, and
     probe_mask=4 means only the third slot.
@@ -2267,6 +2274,10 @@ case above again, the first two slots are already reserved.  If any
 other driver (e.g. snd-usb-audio) is loaded before snd-interwave or
 snd-ens1371, it will be assigned to the third or later slot.
 
+When a module name is given with '!', the slot will be given for any
+modules but that name.  For example, "slots=!snd-pcsp" will reserve
+the first slot for any modules but snd-pcsp. 
+
 
 ALSA PCM devices to OSS devices mapping
 =======================================
index b03df4d..e13c4e6 100644 (file)
@@ -6127,8 +6127,8 @@ struct _snd_pcm_runtime {
 
       <para>
         <function>snd_printdd()</function> is compiled in only when
-      <constant>CONFIG_SND_DEBUG_DETECT</constant> is set. Please note
-      that <constant>DEBUG_DETECT</constant> is not set as default
+      <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is set. Please note
+      that <constant>CONFIG_SND_DEBUG_VERBOSE</constant> is not set as default
       even if you configure the alsa-driver with
       <option>--with-debug=full</option> option. You need to give
       explicitly <option>--with-debug=detect</option> option instead. 
index 09ad799..45d63c9 100644 (file)
@@ -88,6 +88,7 @@ config PLATFORM_AT32AP
        select MMU
        select PERFORMANCE_COUNTERS
        select HAVE_GPIO_LIB
+       select GENERIC_ALLOCATOR
 
 #
 # CPU types
@@ -147,6 +148,9 @@ config PHYS_OFFSET
 
 source "kernel/Kconfig.preempt"
 
+config QUICKLIST
+       def_bool y
+
 config HAVE_ARCH_BOOTMEM_NODE
        def_bool n
 
@@ -201,6 +205,11 @@ endmenu
 
 menu "Power management options"
 
+source "kernel/power/Kconfig"
+
+config ARCH_SUSPEND_POSSIBLE
+       def_bool y
+
 menu "CPU Frequency scaling"
 
 source "drivers/cpufreq/Kconfig"
index a398be2..a51bb9f 100644 (file)
@@ -9,6 +9,8 @@
  */
 #include <linux/clk.h>
 #include <linux/etherdevice.h>
+#include <linux/irq.h>
+#include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
 #include <linux/init.h>
 #include <linux/linkage.h>
 #include <asm/arch/init.h>
 #include <asm/arch/portmux.h>
 
+/* Oscillator frequencies. These are board-specific */
+unsigned long at32_board_osc_rates[3] = {
+       [0] = 32768,    /* 32.768 kHz on RTC osc */
+       [1] = 20000000, /* 20 MHz on osc0 */
+       [2] = 12000000, /* 12 MHz on osc1 */
+};
+
 /* Initialized by bootloader-specific startup code. */
 struct tag *bootloader_tags __initdata;
 
@@ -140,6 +149,10 @@ static struct platform_device i2c_gpio_device = {
        },
 };
 
+static struct i2c_board_info __initdata i2c_info[] = {
+       /* NOTE:  original ATtiny24 firmware is at address 0x0b */
+};
+
 static int __init atngw100_init(void)
 {
        unsigned        i;
@@ -165,12 +178,28 @@ static int __init atngw100_init(void)
        }
        platform_device_register(&ngw_gpio_leds);
 
+       /* all these i2c/smbus pins should have external pullups for
+        * open-drain sharing among all I2C devices.  SDA and SCL do;
+        * PB28/EXTINT3 doesn't; it should be SMBALERT# (for PMBus),
+        * but it's not available off-board.
+        */
+       at32_select_periph(GPIO_PIN_PB(28), 0, AT32_GPIOF_PULLUP);
        at32_select_gpio(i2c_gpio_data.sda_pin,
                AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
        at32_select_gpio(i2c_gpio_data.scl_pin,
                AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH);
        platform_device_register(&i2c_gpio_device);
+       i2c_register_board_info(0, i2c_info, ARRAY_SIZE(i2c_info));
 
        return 0;
 }
 postcore_initcall(atngw100_init);
+
+static int __init atngw100_arch_init(void)
+{
+       /* set_irq_type() after the arch_initcall for EIC has run, and
+        * before the I2C subsystem could try using this IRQ.
+        */
+       return set_irq_type(AT32_EXTINT(3), IRQ_TYPE_EDGE_FALLING);
+}
+arch_initcall(atngw100_arch_init);
index 000eb42..86b363c 100644 (file)
 
 #include "atstk1000.h"
 
+/* Oscillator frequencies. These are board specific */
+unsigned long at32_board_osc_rates[3] = {
+       [0] = 32768,    /* 32.768 kHz on RTC osc */
+       [1] = 20000000, /* 20 MHz on osc0 */
+       [2] = 12000000, /* 12 MHz on osc1 */
+};
 
 struct eth_addr {
        u8 addr[6];
@@ -232,7 +238,7 @@ static int __init atstk1002_init(void)
        set_hw_addr(at32_add_device_eth(1, &eth_data[1]));
 #else
        at32_add_device_lcdc(0, &atstk1000_lcdc_data,
-                            fbmem_start, fbmem_size);
+                            fbmem_start, fbmem_size, 0);
 #endif
        at32_add_device_usba(0, NULL);
 #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
index a0b223d..ea109f4 100644 (file)
 
 #include "atstk1000.h"
 
+/* Oscillator frequencies. These are board specific */
+unsigned long at32_board_osc_rates[3] = {
+       [0] = 32768,    /* 32.768 kHz on RTC osc */
+       [1] = 20000000, /* 20 MHz on osc0 */
+       [2] = 12000000, /* 12 MHz on osc1 */
+};
+
 #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
 static struct at73c213_board_info at73c213_data = {
        .ssc_id         = 0,
index e765a86..c7236df 100644 (file)
 
 #include "atstk1000.h"
 
+/* Oscillator frequencies. These are board specific */
+unsigned long at32_board_osc_rates[3] = {
+       [0] = 32768,    /* 32.768 kHz on RTC osc */
+       [1] = 20000000, /* 20 MHz on osc0 */
+       [2] = 12000000, /* 12 MHz on osc1 */
+};
+
 #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC
 static struct at73c213_board_info at73c213_data = {
        .ssc_id         = 0,
@@ -133,7 +140,7 @@ static int __init atstk1004_init(void)
        at32_add_device_mci(0);
 #endif
        at32_add_device_lcdc(0, &atstk1000_lcdc_data,
-                            fbmem_start, fbmem_size);
+                            fbmem_start, fbmem_size, 0);
        at32_add_device_usba(0, NULL);
 #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM
        at32_add_device_ssc(0, ATMEL_SSC_TX);
index 5f31702..2b398ca 100644 (file)
@@ -74,50 +74,41 @@ exception_vectors:
        .align  2
        bral    do_dtlb_modified
 
-       /*
-        * r0 : PGD/PT/PTE
-        * r1 : Offending address
-        * r2 : Scratch register
-        * r3 : Cause (5, 12 or 13)
-        */
 #define        tlbmiss_save    pushm   r0-r3
 #define tlbmiss_restore        popm    r0-r3
 
-       .section .tlbx.ex.text,"ax",@progbits
+       .org    0x50
        .global itlb_miss
 itlb_miss:
        tlbmiss_save
        rjmp    tlb_miss_common
 
-       .section .tlbr.ex.text,"ax",@progbits
+       .org    0x60
 dtlb_miss_read:
        tlbmiss_save
        rjmp    tlb_miss_common
 
-       .section .tlbw.ex.text,"ax",@progbits
+       .org    0x70
 dtlb_miss_write:
        tlbmiss_save
 
        .global tlb_miss_common
+       .align  2
 tlb_miss_common:
        mfsr    r0, SYSREG_TLBEAR
        mfsr    r1, SYSREG_PTBR
 
-       /* Is it the vmalloc space? */
-       bld     r0, 31
-       brcs    handle_vmalloc_miss
-
-       /* First level lookup */
+       /*
+        * First level lookup: The PGD contains virtual pointers to
+        * the second-level page tables, but they may be NULL if not
+        * present.
+        */
 pgtbl_lookup:
        lsr     r2, r0, PGDIR_SHIFT
        ld.w    r3, r1[r2 << 2]
        bfextu  r1, r0, PAGE_SHIFT, PGDIR_SHIFT - PAGE_SHIFT
-       bld     r3, _PAGE_BIT_PRESENT
-       brcc    page_table_not_present
-
-       /* Translate to virtual address in P1. */
-       andl    r3, 0xf000
-       sbr     r3, 31
+       cp.w    r3, 0
+       breq    page_table_not_present
 
        /* Second level lookup */
        ld.w    r2, r3[r1 << 2]
@@ -148,16 +139,55 @@ pgtbl_lookup:
        tlbmiss_restore
        rete
 
-handle_vmalloc_miss:
-       /* Simply do the lookup in init's page table */
+       /* The slow path of the TLB miss handler */
+       .align  2
+page_table_not_present:
+       /* Do we need to synchronize with swapper_pg_dir? */
+       bld     r0, 31
+       brcs    sync_with_swapper_pg_dir
+
+page_not_present:
+       tlbmiss_restore
+       sub     sp, 4
+       stmts   --sp, r0-lr
+       rcall   save_full_context_ex
+       mfsr    r12, SYSREG_ECR
+       mov     r11, sp
+       rcall   do_page_fault
+       rjmp    ret_from_exception
+
+       .align  2
+sync_with_swapper_pg_dir:
+       /*
+        * If swapper_pg_dir contains a non-NULL second-level page
+        * table pointer, copy it into the current PGD. If not, we
+        * must handle it as a full-blown page fault.
+        *
+        * Jumping back to pgtbl_lookup causes an unnecessary lookup,
+        * but it is guaranteed to be a cache hit, it won't happen
+        * very often, and we absolutely do not want to sacrifice any
+        * performance in the fast path in order to improve this.
+        */
        mov     r1, lo(swapper_pg_dir)
        orh     r1, hi(swapper_pg_dir)
+       ld.w    r3, r1[r2 << 2]
+       cp.w    r3, 0
+       breq    page_not_present
+       mfsr    r1, SYSREG_PTBR
+       st.w    r1[r2 << 2], r3
        rjmp    pgtbl_lookup
 
+       /*
+        * We currently have two bytes left at this point until we
+        * crash into the system call handler...
+        *
+        * Don't worry, the assembler will let us know.
+        */
+
 
        /* ---                    System Call                    --- */
 
-       .section .scall.text,"ax",@progbits
+       .org    0x100
 system_call:
 #ifdef CONFIG_PREEMPT
        mask_interrupts
@@ -266,18 +296,6 @@ syscall_exit_work:
        brcc    syscall_exit_cont
        rjmp    enter_monitor_mode
 
-       /* The slow path of the TLB miss handler */
-page_table_not_present:
-page_not_present:
-       tlbmiss_restore
-       sub     sp, 4
-       stmts   --sp, r0-lr
-       rcall   save_full_context_ex
-       mfsr    r12, SYSREG_ECR
-       mov     r11, sp
-       rcall   do_page_fault
-       rjmp    ret_from_exception
-
        /* This function expects to find offending PC in SYSREG_RAR_EX */
        .type   save_full_context_ex, @function
        .align  2
index 5616a00..c5b11f9 100644 (file)
@@ -93,6 +93,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
+       if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
+               goto badframe;
+
        pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n",
                 regs->pc, regs->lr, regs->sp);
 
index 00a9862..abd954f 100644 (file)
@@ -7,21 +7,13 @@
  */
 #include <linux/clk.h>
 #include <linux/clockchips.h>
-#include <linux/time.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/kernel_stat.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/profile.h>
-#include <linux/sysdev.h>
-#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
 
-#include <asm/div64.h>
 #include <asm/sysreg.h>
-#include <asm/io.h>
-#include <asm/sections.h>
 
 #include <asm/arch/pm.h>
 
index 481cfd4..5d25d8e 100644 (file)
@@ -68,14 +68,6 @@ SECTIONS
                _evba = .;
                _text = .;
                *(.ex.text)
-               . = 0x50;
-               *(.tlbx.ex.text)
-               . = 0x60;
-               *(.tlbr.ex.text)
-               . = 0x70;
-               *(.tlbw.ex.text)
-               . = 0x100;
-               *(.scall.text)
                *(.irq.text)
                KPROBES_TEXT
                TEXT_TEXT
@@ -107,6 +99,10 @@ SECTIONS
                 */
                *(.data.init_task)
 
+               /* Then, the page-aligned data */
+               . = ALIGN(PAGE_SIZE);
+               *(.data.page_aligned)
+
                /* Then, the cacheline aligned data */
                . = ALIGN(L1_CACHE_BYTES);
                *(.data.cacheline_aligned)
index 2be5da7..cb2d869 100644 (file)
@@ -41,7 +41,7 @@ __raw_readsb:
 2:     sub     r10, -4
        reteq   r12
 
-3:     ld.uh   r8, r12[0]
+3:     ld.ub   r8, r12[0]
        sub     r10, 1
        st.b    r11++, r8
        brne    3b
index e890094..d5018e2 100644 (file)
@@ -1,3 +1,8 @@
-obj-y                          += at32ap.o clock.o intc.o extint.o pio.o hsmc.o
+obj-y                          += pdc.o clock.o intc.o extint.o pio.o hsmc.o
 obj-$(CONFIG_CPU_AT32AP700X)   += at32ap700x.o pm-at32ap700x.o
 obj-$(CONFIG_CPU_FREQ_AT32AP)  += cpufreq.o
+obj-$(CONFIG_PM)               += pm.o
+
+ifeq ($(CONFIG_PM_DEBUG),y)
+CFLAGS_pm.o    += -DDEBUG
+endif
index 0f24b4f..07b21b1 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/arch/at32ap700x.h>
 #include <asm/arch/board.h>
 #include <asm/arch/portmux.h>
+#include <asm/arch/sram.h>
 
 #include <video/atmel_lcdc.h>
 
@@ -93,19 +94,12 @@ static struct clk devname##_##_name = {                             \
 
 static DEFINE_SPINLOCK(pm_lock);
 
-unsigned long at32ap7000_osc_rates[3] = {
-       [0] = 32768,
-       /* FIXME: these are ATSTK1002-specific */
-       [1] = 20000000,
-       [2] = 12000000,
-};
-
 static struct clk osc0;
 static struct clk osc1;
 
 static unsigned long osc_get_rate(struct clk *clk)
 {
-       return at32ap7000_osc_rates[clk->index];
+       return at32_board_osc_rates[clk->index];
 }
 
 static unsigned long pll_get_rate(struct clk *clk, unsigned long control)
@@ -682,6 +676,14 @@ static struct clk hramc_clk = {
        .users          = 1,
        .index          = 3,
 };
+static struct clk sdramc_clk = {
+       .name           = "sdramc_clk",
+       .parent         = &pbb_clk,
+       .mode           = pbb_clk_mode,
+       .get_rate       = pbb_clk_get_rate,
+       .users          = 1,
+       .index          = 14,
+};
 
 static struct resource smc0_resource[] = {
        PBMEM(0xfff03400),
@@ -841,6 +843,81 @@ void __init at32_add_system_devices(void)
 }
 
 /* --------------------------------------------------------------------
+ *  PSIF
+ * -------------------------------------------------------------------- */
+static struct resource atmel_psif0_resource[] __initdata = {
+       {
+               .start  = 0xffe03c00,
+               .end    = 0xffe03cff,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ(18),
+};
+static struct clk atmel_psif0_pclk = {
+       .name           = "pclk",
+       .parent         = &pba_clk,
+       .mode           = pba_clk_mode,
+       .get_rate       = pba_clk_get_rate,
+       .index          = 15,
+};
+
+static struct resource atmel_psif1_resource[] __initdata = {
+       {
+               .start  = 0xffe03d00,
+               .end    = 0xffe03dff,
+               .flags  = IORESOURCE_MEM,
+       },
+       IRQ(18),
+};
+static struct clk atmel_psif1_pclk = {
+       .name           = "pclk",
+       .parent         = &pba_clk,
+       .mode           = pba_clk_mode,
+       .get_rate       = pba_clk_get_rate,
+       .index          = 15,
+};
+
+struct platform_device *__init at32_add_device_psif(unsigned int id)
+{
+       struct platform_device *pdev;
+
+       if (!(id == 0 || id == 1))
+               return NULL;
+
+       pdev = platform_device_alloc("atmel_psif", id);
+       if (!pdev)
+               return NULL;
+
+       switch (id) {
+       case 0:
+               if (platform_device_add_resources(pdev, atmel_psif0_resource,
+                                       ARRAY_SIZE(atmel_psif0_resource)))
+                       goto err_add_resources;
+               atmel_psif0_pclk.dev = &pdev->dev;
+               select_peripheral(PA(8), PERIPH_A, 0); /* CLOCK */
+               select_peripheral(PA(9), PERIPH_A, 0); /* DATA  */
+               break;
+       case 1:
+               if (platform_device_add_resources(pdev, atmel_psif1_resource,
+                                       ARRAY_SIZE(atmel_psif1_resource)))
+                       goto err_add_resources;
+               atmel_psif1_pclk.dev = &pdev->dev;
+               select_peripheral(PB(11), PERIPH_A, 0); /* CLOCK */
+               select_peripheral(PB(12), PERIPH_A, 0); /* DATA  */
+               break;
+       default:
+               return NULL;
+       }
+
+       platform_device_add(pdev);
+       return pdev;
+
+err_add_resources:
+       platform_device_put(pdev);
+       return NULL;
+}
+
+/* --------------------------------------------------------------------
  *  USART
  * -------------------------------------------------------------------- */
 
@@ -1113,7 +1190,8 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
        switch (id) {
        case 0:
                pdev = &atmel_spi0_device;
-               select_peripheral(PA(0),  PERIPH_A, 0); /* MISO  */
+               /* pullup MISO so a level is always defined */
+               select_peripheral(PA(0),  PERIPH_A, AT32_GPIOF_PULLUP);
                select_peripheral(PA(1),  PERIPH_A, 0); /* MOSI  */
                select_peripheral(PA(2),  PERIPH_A, 0); /* SCK   */
                at32_spi_setup_slaves(0, b, n, spi0_pins);
@@ -1121,7 +1199,8 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n)
 
        case 1:
                pdev = &atmel_spi1_device;
-               select_peripheral(PB(0),  PERIPH_B, 0); /* MISO  */
+               /* pullup MISO so a level is always defined */
+               select_peripheral(PB(0),  PERIPH_B, AT32_GPIOF_PULLUP);
                select_peripheral(PB(1),  PERIPH_B, 0); /* MOSI  */
                select_peripheral(PB(5),  PERIPH_B, 0); /* SCK   */
                at32_spi_setup_slaves(1, b, n, spi1_pins);
@@ -1264,7 +1343,8 @@ static struct clk atmel_lcdfb0_pixclk = {
 
 struct platform_device *__init
 at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
-                    unsigned long fbmem_start, unsigned long fbmem_len)
+                    unsigned long fbmem_start, unsigned long fbmem_len,
+                    unsigned int pin_config)
 {
        struct platform_device *pdev;
        struct atmel_lcdfb_info *info;
@@ -1291,37 +1371,77 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
        switch (id) {
        case 0:
                pdev = &atmel_lcdfb0_device;
-               select_peripheral(PC(19), PERIPH_A, 0); /* CC     */
-               select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC  */
-               select_peripheral(PC(21), PERIPH_A, 0); /* PCLK   */
-               select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC  */
-               select_peripheral(PC(23), PERIPH_A, 0); /* DVAL   */
-               select_peripheral(PC(24), PERIPH_A, 0); /* MODE   */
-               select_peripheral(PC(25), PERIPH_A, 0); /* PWR    */
-               select_peripheral(PC(26), PERIPH_A, 0); /* DATA0  */
-               select_peripheral(PC(27), PERIPH_A, 0); /* DATA1  */
-               select_peripheral(PC(28), PERIPH_A, 0); /* DATA2  */
-               select_peripheral(PC(29), PERIPH_A, 0); /* DATA3  */
-               select_peripheral(PC(30), PERIPH_A, 0); /* DATA4  */
-               select_peripheral(PC(31), PERIPH_A, 0); /* DATA5  */
-               select_peripheral(PD(0),  PERIPH_A, 0); /* DATA6  */
-               select_peripheral(PD(1),  PERIPH_A, 0); /* DATA7  */
-               select_peripheral(PD(2),  PERIPH_A, 0); /* DATA8  */
-               select_peripheral(PD(3),  PERIPH_A, 0); /* DATA9  */
-               select_peripheral(PD(4),  PERIPH_A, 0); /* DATA10 */
-               select_peripheral(PD(5),  PERIPH_A, 0); /* DATA11 */
-               select_peripheral(PD(6),  PERIPH_A, 0); /* DATA12 */
-               select_peripheral(PD(7),  PERIPH_A, 0); /* DATA13 */
-               select_peripheral(PD(8),  PERIPH_A, 0); /* DATA14 */
-               select_peripheral(PD(9),  PERIPH_A, 0); /* DATA15 */
-               select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
-               select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
-               select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
-               select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
-               select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
-               select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
-               select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
-               select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
+
+               switch (pin_config) {
+               case 0:
+                       select_peripheral(PC(19), PERIPH_A, 0); /* CC     */
+                       select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC  */
+                       select_peripheral(PC(21), PERIPH_A, 0); /* PCLK   */
+                       select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC  */
+                       select_peripheral(PC(23), PERIPH_A, 0); /* DVAL   */
+                       select_peripheral(PC(24), PERIPH_A, 0); /* MODE   */
+                       select_peripheral(PC(25), PERIPH_A, 0); /* PWR    */
+                       select_peripheral(PC(26), PERIPH_A, 0); /* DATA0  */
+                       select_peripheral(PC(27), PERIPH_A, 0); /* DATA1  */
+                       select_peripheral(PC(28), PERIPH_A, 0); /* DATA2  */
+                       select_peripheral(PC(29), PERIPH_A, 0); /* DATA3  */
+                       select_peripheral(PC(30), PERIPH_A, 0); /* DATA4  */
+                       select_peripheral(PC(31), PERIPH_A, 0); /* DATA5  */
+                       select_peripheral(PD(0),  PERIPH_A, 0); /* DATA6  */
+                       select_peripheral(PD(1),  PERIPH_A, 0); /* DATA7  */
+                       select_peripheral(PD(2),  PERIPH_A, 0); /* DATA8  */
+                       select_peripheral(PD(3),  PERIPH_A, 0); /* DATA9  */
+                       select_peripheral(PD(4),  PERIPH_A, 0); /* DATA10 */
+                       select_peripheral(PD(5),  PERIPH_A, 0); /* DATA11 */
+                       select_peripheral(PD(6),  PERIPH_A, 0); /* DATA12 */
+                       select_peripheral(PD(7),  PERIPH_A, 0); /* DATA13 */
+                       select_peripheral(PD(8),  PERIPH_A, 0); /* DATA14 */
+                       select_peripheral(PD(9),  PERIPH_A, 0); /* DATA15 */
+                       select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */
+                       select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */
+                       select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */
+                       select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */
+                       select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */
+                       select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */
+                       select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
+                       select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
+                       break;
+               case 1:
+                       select_peripheral(PE(0),  PERIPH_B, 0); /* CC     */
+                       select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC  */
+                       select_peripheral(PC(21), PERIPH_A, 0); /* PCLK   */
+                       select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC  */
+                       select_peripheral(PE(1),  PERIPH_B, 0); /* DVAL   */
+                       select_peripheral(PE(2),  PERIPH_B, 0); /* MODE   */
+                       select_peripheral(PC(25), PERIPH_A, 0); /* PWR    */
+                       select_peripheral(PE(3),  PERIPH_B, 0); /* DATA0  */
+                       select_peripheral(PE(4),  PERIPH_B, 0); /* DATA1  */
+                       select_peripheral(PE(5),  PERIPH_B, 0); /* DATA2  */
+                       select_peripheral(PE(6),  PERIPH_B, 0); /* DATA3  */
+                       select_peripheral(PE(7),  PERIPH_B, 0); /* DATA4  */
+                       select_peripheral(PC(31), PERIPH_A, 0); /* DATA5  */
+                       select_peripheral(PD(0),  PERIPH_A, 0); /* DATA6  */
+                       select_peripheral(PD(1),  PERIPH_A, 0); /* DATA7  */
+                       select_peripheral(PE(8),  PERIPH_B, 0); /* DATA8  */
+                       select_peripheral(PE(9),  PERIPH_B, 0); /* DATA9  */
+                       select_peripheral(PE(10), PERIPH_B, 0); /* DATA10 */
+                       select_peripheral(PE(11), PERIPH_B, 0); /* DATA11 */
+                       select_peripheral(PE(12), PERIPH_B, 0); /* DATA12 */
+                       select_peripheral(PD(7),  PERIPH_A, 0); /* DATA13 */
+                       select_peripheral(PD(8),  PERIPH_A, 0); /* DATA14 */
+                       select_peripheral(PD(9),  PERIPH_A, 0); /* DATA15 */
+                       select_peripheral(PE(13), PERIPH_B, 0); /* DATA16 */
+                       select_peripheral(PE(14), PERIPH_B, 0); /* DATA17 */
+                       select_peripheral(PE(15), PERIPH_B, 0); /* DATA18 */
+                       select_peripheral(PE(16), PERIPH_B, 0); /* DATA19 */
+                       select_peripheral(PE(17), PERIPH_B, 0); /* DATA20 */
+                       select_peripheral(PE(18), PERIPH_B, 0); /* DATA21 */
+                       select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */
+                       select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */
+                       break;
+               default:
+                       goto err_invalid_id;
+               }
 
                clk_set_parent(&atmel_lcdfb0_pixclk, &pll0);
                clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0));
@@ -1360,7 +1480,7 @@ static struct resource atmel_pwm0_resource[] __initdata = {
        IRQ(24),
 };
 static struct clk atmel_pwm0_mck = {
-       .name           = "mck",
+       .name           = "pwm_clk",
        .parent         = &pbb_clk,
        .mode           = pbb_clk_mode,
        .get_rate       = pbb_clk_get_rate,
@@ -1887,6 +2007,7 @@ struct clk *at32_clock_list[] = {
        &hmatrix_clk,
        &ebi_clk,
        &hramc_clk,
+       &sdramc_clk,
        &smc0_pclk,
        &smc0_mck,
        &pdc_hclk,
@@ -1900,6 +2021,8 @@ struct clk *at32_clock_list[] = {
        &pio4_mck,
        &at32_tcb0_t0_clk,
        &at32_tcb1_t0_clk,
+       &atmel_psif0_pclk,
+       &atmel_psif1_pclk,
        &atmel_usart0_usart,
        &atmel_usart1_usart,
        &atmel_usart2_usart,
@@ -1935,16 +2058,7 @@ struct clk *at32_clock_list[] = {
 };
 unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list);
 
-void __init at32_portmux_init(void)
-{
-       at32_init_pio(&pio0_device);
-       at32_init_pio(&pio1_device);
-       at32_init_pio(&pio2_device);
-       at32_init_pio(&pio3_device);
-       at32_init_pio(&pio4_device);
-}
-
-void __init at32_clock_init(void)
+void __init setup_platform(void)
 {
        u32 cpu_mask = 0, hsb_mask = 0, pba_mask = 0, pbb_mask = 0;
        int i;
@@ -1999,4 +2113,36 @@ void __init at32_clock_init(void)
        pm_writel(HSB_MASK, hsb_mask);
        pm_writel(PBA_MASK, pba_mask);
        pm_writel(PBB_MASK, pbb_mask);
+
+       /* Initialize the port muxes */
+       at32_init_pio(&pio0_device);
+       at32_init_pio(&pio1_device);
+       at32_init_pio(&pio2_device);
+       at32_init_pio(&pio3_device);
+       at32_init_pio(&pio4_device);
+}
+
+struct gen_pool *sram_pool;
+
+static int __init sram_init(void)
+{
+       struct gen_pool *pool;
+
+       /* 1KiB granularity */
+       pool = gen_pool_create(10, -1);
+       if (!pool)
+               goto fail;
+
+       if (gen_pool_add(pool, 0x24000000, 0x8000, -1))
+               goto err_pool_add;
+
+       sram_pool = pool;
+       return 0;
+
+err_pool_add:
+       gen_pool_destroy(pool);
+fail:
+       pr_err("Failed to create SRAM pool\n");
+       return -ENOMEM;
 }
+core_initcall(sram_init);
index 097cf4e..994c454 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Atmel Corporation
+ * Copyright (C) 2006, 2008 Atmel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
+#include <linux/sysdev.h>
 
 #include <asm/io.h>
 
 #include "intc.h"
 
 struct intc {
-       void __iomem    *regs;
-       struct irq_chip chip;
+       void __iomem            *regs;
+       struct irq_chip         chip;
+       struct sys_device       sysdev;
+#ifdef CONFIG_PM
+       unsigned long           suspend_ipr;
+       unsigned long           saved_ipr[64];
+#endif
 };
 
 extern struct platform_device at32_intc0_device;
@@ -136,6 +142,74 @@ fail:
        panic("Interrupt controller initialization failed!\n");
 }
 
+#ifdef CONFIG_PM
+void intc_set_suspend_handler(unsigned long offset)
+{
+       intc0.suspend_ipr = offset;
+}
+
+static int intc_suspend(struct sys_device *sdev, pm_message_t state)
+{
+       struct intc *intc = container_of(sdev, struct intc, sysdev);
+       int i;
+
+       if (unlikely(!irqs_disabled())) {
+               pr_err("intc_suspend: called with interrupts enabled\n");
+               return -EINVAL;
+       }
+
+       if (unlikely(!intc->suspend_ipr)) {
+               pr_err("intc_suspend: suspend_ipr not initialized\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < 64; i++) {
+               intc->saved_ipr[i] = intc_readl(intc, INTPR0 + 4 * i);
+               intc_writel(intc, INTPR0 + 4 * i, intc->suspend_ipr);
+       }
+
+       return 0;
+}
+
+static int intc_resume(struct sys_device *sdev)
+{
+       struct intc *intc = container_of(sdev, struct intc, sysdev);
+       int i;
+
+       WARN_ON(!irqs_disabled());
+
+       for (i = 0; i < 64; i++)
+               intc_writel(intc, INTPR0 + 4 * i, intc->saved_ipr[i]);
+
+       return 0;
+}
+#else
+#define intc_suspend   NULL
+#define intc_resume    NULL
+#endif
+
+static struct sysdev_class intc_class = {
+       .name           = "intc",
+       .suspend        = intc_suspend,
+       .resume         = intc_resume,
+};
+
+static int __init intc_init_sysdev(void)
+{
+       int ret;
+
+       ret = sysdev_class_register(&intc_class);
+       if (ret)
+               return ret;
+
+       intc0.sysdev.id = 0;
+       intc0.sysdev.cls = &intc_class;
+       ret = sysdev_register(&intc0.sysdev);
+
+       return ret;
+}
+device_initcall(intc_init_sysdev);
+
 unsigned long intc_get_pending(unsigned int group)
 {
        return intc_readl(&intc0, INTREQ0 + 4 * group);
similarity index 90%
rename from arch/avr32/mach-at32ap/at32ap.c
rename to arch/avr32/mach-at32ap/pdc.c
index 7c4987f..1040bda 100644 (file)
 #include <linux/init.h>
 #include <linux/platform_device.h>
 
-#include <asm/arch/init.h>
-
-void __init setup_platform(void)
-{
-       at32_clock_init();
-       at32_portmux_init();
-}
-
 static int __init pdc_probe(struct platform_device *pdev)
 {
        struct clk *pclk, *hclk;
index 38a8fa3..60da03b 100644 (file)
@@ -318,6 +318,8 @@ static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
                const char *label;
 
                label = gpiochip_is_requested(chip, i);
+               if (!label && (imr & mask))
+                       label = "[irq]";
                if (!label)
                        continue;
 
index 7795116..9484dfc 100644 (file)
@@ -57,7 +57,7 @@
 
 /* Bitfields in IFDR */
 
-/* Bitfields in ISFR */
+/* Bitfields in IFSR */
 
 /* Bitfields in SODR */
 
index 949e248..0a53ad3 100644 (file)
 #include <asm/thread_info.h>
 #include <asm/arch/pm.h>
 
+#include "pm.h"
+#include "sdramc.h"
+
+/* Same as 0xfff00000 but fits in a 21 bit signed immediate */
+#define PM_BASE        -0x100000
+
        .section .bss, "wa", @nobits
        .global disable_idle_sleep
        .type   disable_idle_sleep, @object
@@ -64,3 +70,105 @@ cpu_idle_skip_sleep:
        unmask_interrupts
        retal   r12
        .size   cpu_idle_skip_sleep, . - cpu_idle_skip_sleep
+
+#ifdef CONFIG_PM
+       .section .init.text, "ax", @progbits
+
+       .global pm_exception
+       .type   pm_exception, @function
+pm_exception:
+       /*
+        * Exceptions are masked when we switch to this handler, so
+        * we'll only get "unrecoverable" exceptions (offset 0.)
+        */
+       sub     r12, pc, . - .Lpanic_msg
+       lddpc   pc, .Lpanic_addr
+
+       .align  2
+.Lpanic_addr:
+       .long   panic
+.Lpanic_msg:
+       .asciz  "Unrecoverable exception during suspend\n"
+       .size   pm_exception, . - pm_exception
+
+       .global pm_irq0
+       .type   pm_irq0, @function
+pm_irq0:
+       /* Disable interrupts and return after the sleep instruction */
+       mfsr    r9, SYSREG_RSR_INT0
+       mtsr    SYSREG_RAR_INT0, r8
+       sbr     r9, SYSREG_GM_OFFSET
+       mtsr    SYSREG_RSR_INT0, r9
+       rete
+
+       /*
+        * void cpu_enter_standby(unsigned long sdramc_base)
+        *
+        * Enter PM_SUSPEND_STANDBY mode. At this point, all drivers
+        * are suspended and interrupts are disabled. Interrupts
+        * marked as 'wakeup' event sources may still come along and
+        * get us out of here.
+        *
+        * The SDRAM will be put into self-refresh mode (which does
+        * not require a clock from the CPU), and the CPU will be put
+        * into "frozen" mode (HSB bus stopped). The SDRAM controller
+        * will automatically bring the SDRAM into normal mode on the
+        * first access, and the power manager will automatically
+        * start the HSB and CPU clocks upon a wakeup event.
+        *
+        * This code uses the same "skip sleep" technique as above.
+        * It is very important that we jump directly to
+        * cpu_after_sleep after the sleep instruction since that's
+        * where we'll end up if the interrupt handler decides that we
+        * need to skip the sleep instruction.
+        */
+       .global pm_standby
+       .type   pm_standby, @function
+pm_standby:
+       /*
+        * interrupts are already masked at this point, and EVBA
+        * points to pm_exception above.
+        */
+       ld.w    r10, r12[SDRAMC_LPR]
+       sub     r8, pc, . - 1f          /* return address for irq handler */
+       mov     r11, SDRAMC_LPR_LPCB_SELF_RFR
+       bfins   r10, r11, 0, 2          /* LPCB <- self Refresh */
+       sync    0                       /* flush write buffer */
+       st.w    r12[SDRAMC_LPR], r11    /* put SDRAM in self-refresh mode */
+       ld.w    r11, r12[SDRAMC_LPR]
+       unmask_interrupts
+       sleep   CPU_SLEEP_FROZEN
+1:     mask_interrupts
+       retal   r12
+       .size   pm_standby, . - pm_standby
+
+       .global pm_suspend_to_ram
+       .type   pm_suspend_to_ram, @function
+pm_suspend_to_ram:
+       /*
+        * interrupts are already masked at this point, and EVBA
+        * points to pm_exception above.
+        */
+       mov     r11, 0
+       cache   r11[2], 8               /* clean all dcache lines */
+       sync    0                       /* flush write buffer */
+       ld.w    r10, r12[SDRAMC_LPR]
+       sub     r8, pc, . - 1f          /* return address for irq handler */
+       mov     r11, SDRAMC_LPR_LPCB_SELF_RFR
+       bfins   r10, r11, 0, 2          /* LPCB <- self refresh */
+       st.w    r12[SDRAMC_LPR], r10    /* put SDRAM in self-refresh mode */
+       ld.w    r11, r12[SDRAMC_LPR]
+
+       unmask_interrupts
+       sleep   CPU_SLEEP_STOP
+1:     mask_interrupts
+
+       retal   r12
+       .size   pm_suspend_to_ram, . - pm_suspend_to_ram
+
+       .global pm_sram_end
+       .type   pm_sram_end, @function
+pm_sram_end:
+       .size   pm_sram_end, 0
+
+#endif /* CONFIG_PM */
diff --git a/arch/avr32/mach-at32ap/pm.c b/arch/avr32/mach-at32ap/pm.c
new file mode 100644 (file)
index 0000000..0b76432
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * AVR32 AP Power Management
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+#include <linux/io.h>
+#include <linux/suspend.h>
+#include <linux/vmalloc.h>
+
+#include <asm/cacheflush.h>
+#include <asm/sysreg.h>
+
+#include <asm/arch/pm.h>
+#include <asm/arch/sram.h>
+
+/* FIXME: This is only valid for AP7000 */
+#define SDRAMC_BASE    0xfff03800
+
+#include "sdramc.h"
+
+#define SRAM_PAGE_FLAGS        (SYSREG_BIT(TLBELO_D) | SYSREG_BF(SZ, 1)        \
+                               | SYSREG_BF(AP, 3) | SYSREG_BIT(G))
+
+
+static unsigned long   pm_sram_start;
+static size_t          pm_sram_size;
+static struct vm_struct        *pm_sram_area;
+
+static void (*avr32_pm_enter_standby)(unsigned long sdramc_base);
+static void (*avr32_pm_enter_str)(unsigned long sdramc_base);
+
+/*
+ * Must be called with interrupts disabled. Exceptions will be masked
+ * on return (i.e. all exceptions will be "unrecoverable".)
+ */
+static void *avr32_pm_map_sram(void)
+{
+       unsigned long   vaddr;
+       unsigned long   page_addr;
+       u32             tlbehi;
+       u32             mmucr;
+
+       vaddr = (unsigned long)pm_sram_area->addr;
+       page_addr = pm_sram_start & PAGE_MASK;
+
+       /*
+        * Mask exceptions and grab the first TLB entry. We won't be
+        * needing it while sleeping.
+        */
+       asm volatile("ssrf      %0" : : "i"(SYSREG_EM_OFFSET) : "memory");
+
+       mmucr = sysreg_read(MMUCR);
+       tlbehi = sysreg_read(TLBEHI);
+       sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr));
+
+       tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
+       tlbehi |= vaddr & PAGE_MASK;
+       tlbehi |= SYSREG_BIT(TLBEHI_V);
+
+       sysreg_write(TLBELO, page_addr | SRAM_PAGE_FLAGS);
+       sysreg_write(TLBEHI, tlbehi);
+       __builtin_tlbw();
+
+       return (void *)(vaddr + pm_sram_start - page_addr);
+}
+
+/*
+ * Must be called with interrupts disabled. Exceptions will be
+ * unmasked on return.
+ */
+static void avr32_pm_unmap_sram(void)
+{
+       u32     mmucr;
+       u32     tlbehi;
+       u32     tlbarlo;
+
+       /* Going to update TLB entry at index 0 */
+       mmucr = sysreg_read(MMUCR);
+       tlbehi = sysreg_read(TLBEHI);
+       sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr));
+
+       /* Clear the "valid" bit */
+       tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
+       sysreg_write(TLBEHI, tlbehi);
+
+       /* Mark it as "not accessed" */
+       tlbarlo = sysreg_read(TLBARLO);
+       sysreg_write(TLBARLO, tlbarlo | 0x80000000U);
+
+       /* Update the TLB */
+       __builtin_tlbw();
+
+       /* Unmask exceptions */
+       asm volatile("csrf      %0" : : "i"(SYSREG_EM_OFFSET) : "memory");
+}
+
+static int avr32_pm_valid_state(suspend_state_t state)
+{
+       switch (state) {
+       case PM_SUSPEND_ON:
+       case PM_SUSPEND_STANDBY:
+       case PM_SUSPEND_MEM:
+               return 1;
+
+       default:
+               return 0;
+       }
+}
+
+static int avr32_pm_enter(suspend_state_t state)
+{
+       u32             lpr_saved;
+       u32             evba_saved;
+       void            *sram;
+
+       switch (state) {
+       case PM_SUSPEND_STANDBY:
+               sram = avr32_pm_map_sram();
+
+               /* Switch to in-sram exception handlers */
+               evba_saved = sysreg_read(EVBA);
+               sysreg_write(EVBA, (unsigned long)sram);
+
+               /*
+                * Save the LPR register so that we can re-enable
+                * SDRAM Low Power mode on resume.
+                */
+               lpr_saved = sdramc_readl(LPR);
+               pr_debug("%s: Entering standby...\n", __func__);
+               avr32_pm_enter_standby(SDRAMC_BASE);
+               sdramc_writel(LPR, lpr_saved);
+
+               /* Switch back to regular exception handlers */
+               sysreg_write(EVBA, evba_saved);
+
+               avr32_pm_unmap_sram();
+               break;
+
+       case PM_SUSPEND_MEM:
+               sram = avr32_pm_map_sram();
+
+               /* Switch to in-sram exception handlers */
+               evba_saved = sysreg_read(EVBA);
+               sysreg_write(EVBA, (unsigned long)sram);
+
+               /*
+                * Save the LPR register so that we can re-enable
+                * SDRAM Low Power mode on resume.
+                */
+               lpr_saved = sdramc_readl(LPR);
+               pr_debug("%s: Entering suspend-to-ram...\n", __func__);
+               avr32_pm_enter_str(SDRAMC_BASE);
+               sdramc_writel(LPR, lpr_saved);
+
+               /* Switch back to regular exception handlers */
+               sysreg_write(EVBA, evba_saved);
+
+               avr32_pm_unmap_sram();
+               break;
+
+       case PM_SUSPEND_ON:
+               pr_debug("%s: Entering idle...\n", __func__);
+               cpu_enter_idle();
+               break;
+
+       default:
+               pr_debug("%s: Invalid suspend state %d\n", __func__, state);
+               goto out;
+       }
+
+       pr_debug("%s: wakeup\n", __func__);
+
+out:
+       return 0;
+}
+
+static struct platform_suspend_ops avr32_pm_ops = {
+       .valid  = avr32_pm_valid_state,
+       .enter  = avr32_pm_enter,
+};
+
+static unsigned long avr32_pm_offset(void *symbol)
+{
+       extern u8 pm_exception[];
+
+       return (unsigned long)symbol - (unsigned long)pm_exception;
+}
+
+static int __init avr32_pm_init(void)
+{
+       extern u8 pm_exception[];
+       extern u8 pm_irq0[];
+       extern u8 pm_standby[];
+       extern u8 pm_suspend_to_ram[];
+       extern u8 pm_sram_end[];
+       void *dst;
+
+       /*
+        * To keep things simple, we depend on not needing more than a
+        * single page.
+        */
+       pm_sram_size = avr32_pm_offset(pm_sram_end);
+       if (pm_sram_size > PAGE_SIZE)
+               goto err;
+
+       pm_sram_start = sram_alloc(pm_sram_size);
+       if (!pm_sram_start)
+               goto err_alloc_sram;
+
+       /* Grab a virtual area we can use later on. */
+       pm_sram_area = get_vm_area(pm_sram_size, VM_IOREMAP);
+       if (!pm_sram_area)
+               goto err_vm_area;
+       pm_sram_area->phys_addr = pm_sram_start;
+
+       local_irq_disable();
+       dst = avr32_pm_map_sram();
+       memcpy(dst, pm_exception, pm_sram_size);
+       flush_dcache_region(dst, pm_sram_size);
+       invalidate_icache_region(dst, pm_sram_size);
+       avr32_pm_unmap_sram();
+       local_irq_enable();
+
+       avr32_pm_enter_standby = dst + avr32_pm_offset(pm_standby);
+       avr32_pm_enter_str = dst + avr32_pm_offset(pm_suspend_to_ram);
+       intc_set_suspend_handler(avr32_pm_offset(pm_irq0));
+
+       suspend_set_ops(&avr32_pm_ops);
+
+       printk("AVR32 AP Power Management enabled\n");
+
+       return 0;
+
+err_vm_area:
+       sram_free(pm_sram_start, pm_sram_size);
+err_alloc_sram:
+err:
+       pr_err("AVR32 Power Management initialization failed\n");
+       return -ENOMEM;
+}
+arch_initcall(avr32_pm_init);
diff --git a/arch/avr32/mach-at32ap/sdramc.h b/arch/avr32/mach-at32ap/sdramc.h
new file mode 100644 (file)
index 0000000..66eeaed
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Register definitions for the AT32AP SDRAM Controller
+ *
+ * Copyright (C) 2008 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+/* Register offsets */
+#define SDRAMC_MR                      0x0000
+#define SDRAMC_TR                      0x0004
+#define SDRAMC_CR                      0x0008
+#define SDRAMC_HSR                     0x000c
+#define SDRAMC_LPR                     0x0010
+#define SDRAMC_IER                     0x0014
+#define SDRAMC_IDR                     0x0018
+#define SDRAMC_IMR                     0x001c
+#define SDRAMC_ISR                     0x0020
+#define SDRAMC_MDR                     0x0024
+
+/* MR - Mode Register */
+#define SDRAMC_MR_MODE_NORMAL          (  0 <<  0)
+#define SDRAMC_MR_MODE_NOP             (  1 <<  0)
+#define SDRAMC_MR_MODE_BANKS_PRECHARGE (  2 <<  0)
+#define SDRAMC_MR_MODE_LOAD_MODE       (  3 <<  0)
+#define SDRAMC_MR_MODE_AUTO_REFRESH    (  4 <<  0)
+#define SDRAMC_MR_MODE_EXT_LOAD_MODE   (  5 <<  0)
+#define SDRAMC_MR_MODE_POWER_DOWN      (  6 <<  0)
+
+/* CR - Configuration Register */
+#define SDRAMC_CR_NC_8_BITS            (  0 <<  0)
+#define SDRAMC_CR_NC_9_BITS            (  1 <<  0)
+#define SDRAMC_CR_NC_10_BITS           (  2 <<  0)
+#define SDRAMC_CR_NC_11_BITS           (  3 <<  0)
+#define SDRAMC_CR_NR_11_BITS           (  0 <<  2)
+#define SDRAMC_CR_NR_12_BITS           (  1 <<  2)
+#define SDRAMC_CR_NR_13_BITS           (  2 <<  2)
+#define SDRAMC_CR_NB_2_BANKS           (  0 <<  4)
+#define SDRAMC_CR_NB_4_BANKS           (  1 <<  4)
+#define SDRAMC_CR_CAS(x)               ((x) <<  5)
+#define SDRAMC_CR_DBW_32_BITS          (  0 <<  7)
+#define SDRAMC_CR_DBW_16_BITS          (  1 <<  7)
+#define SDRAMC_CR_TWR(x)               ((x) <<  8)
+#define SDRAMC_CR_TRC(x)               ((x) << 12)
+#define SDRAMC_CR_TRP(x)               ((x) << 16)
+#define SDRAMC_CR_TRCD(x)              ((x) << 20)
+#define SDRAMC_CR_TRAS(x)              ((x) << 24)
+#define SDRAMC_CR_TXSR(x)              ((x) << 28)
+
+/* HSR - High Speed Register */
+#define SDRAMC_HSR_DA                  (  1 <<  0)
+
+/* LPR - Low Power Register */
+#define SDRAMC_LPR_LPCB_INHIBIT                (  0 <<  0)
+#define SDRAMC_LPR_LPCB_SELF_RFR       (  1 <<  0)
+#define SDRAMC_LPR_LPCB_PDOWN          (  2 <<  0)
+#define SDRAMC_LPR_LPCB_DEEP_PDOWN     (  3 <<  0)
+#define SDRAMC_LPR_PASR(x)             ((x) <<  4)
+#define SDRAMC_LPR_TCSR(x)             ((x) <<  8)
+#define SDRAMC_LPR_DS(x)               ((x) << 10)
+#define SDRAMC_LPR_TIMEOUT(x)          ((x) << 12)
+
+/* IER/IDR/IMR/ISR - Interrupt Enable/Disable/Mask/Status Register */
+#define SDRAMC_ISR_RES                 (  1 <<  0)
+
+/* MDR - Memory Device Register */
+#define SDRAMC_MDR_MD_SDRAM            (  0 <<  0)
+#define SDRAMC_MDR_MD_LOW_PWR_SDRAM    (  1 <<  0)
+
+/* Register access macros */
+#define sdramc_readl(reg) \
+       __raw_readl((void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg)
+#define sdramc_writel(reg, value) \
+       __raw_writel(value, (void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg)
index 0e64ddc..3f90a87 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/swap.h>
 #include <linux/init.h>
 #include <linux/mmzone.h>
+#include <linux/module.h>
 #include <linux/bootmem.h>
 #include <linux/pagemap.h>
 #include <linux/nodemask.h>
 #include <asm/setup.h>
 #include <asm/sections.h>
 
+#define __page_aligned __attribute__((section(".data.page_aligned")))
+
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-pgd_t swapper_pg_dir[PTRS_PER_PGD];
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned;
 
 struct page *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
 
 /*
  * Cache of MMU context last used.
@@ -106,19 +110,9 @@ void __init paging_init(void)
        zero_page = alloc_bootmem_low_pages_node(NODE_DATA(0),
                                                 PAGE_SIZE);
 
-       {
-               pgd_t *pg_dir;
-               int i;
-
-               pg_dir = swapper_pg_dir;
-               sysreg_write(PTBR, (unsigned long)pg_dir);
-
-               for (i = 0; i < PTRS_PER_PGD; i++)
-                       pgd_val(pg_dir[i]) = 0;
-
-               enable_mmu();
-               printk ("CPU: Paging enabled\n");
-       }
+       sysreg_write(PTBR, (unsigned long)swapper_pg_dir);
+       enable_mmu();
+       printk ("CPU: Paging enabled\n");
 
        for_each_online_node(nid) {
                pg_data_t *pgdat = NODE_DATA(nid);
index cd12edb..06677be 100644 (file)
 
 #include <asm/mmu_context.h>
 
-#define _TLBEHI_I      0x100
+/* TODO: Get the correct number from the CONFIG1 system register */
+#define NR_TLB_ENTRIES 32
 
-void show_dtlb_entry(unsigned int index)
+static void show_dtlb_entry(unsigned int index)
 {
-       unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
+       u32 tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
        unsigned long flags;
 
        local_irq_save(flags);
        mmucr_save = sysreg_read(MMUCR);
        tlbehi_save = sysreg_read(TLBEHI);
-       mmucr = mmucr_save & 0x13;
-       mmucr |= index << 14;
+       mmucr = SYSREG_BFINS(DRP, index, mmucr_save);
        sysreg_write(MMUCR, mmucr);
 
-       asm volatile("tlbr" : : : "memory");
+       __builtin_tlbr();
        cpu_sync_pipeline();
 
        tlbehi = sysreg_read(TLBEHI);
@@ -33,15 +33,17 @@ void show_dtlb_entry(unsigned int index)
 
        printk("%2u: %c %c %02x   %05x %05x %o  %o  %c %c %c %c\n",
               index,
-              (tlbehi & 0x200)?'1':'0',
-              (tlbelo & 0x100)?'1':'0',
-              (tlbehi & 0xff),
-              (tlbehi >> 12), (tlbelo >> 12),
-              (tlbelo >> 4) & 7, (tlbelo >> 2) & 3,
-              (tlbelo & 0x200)?'1':'0',
-              (tlbelo & 0x080)?'1':'0',
-              (tlbelo & 0x001)?'1':'0',
-              (tlbelo & 0x002)?'1':'0');
+              SYSREG_BFEXT(TLBEHI_V, tlbehi) ? '1' : '0',
+              SYSREG_BFEXT(G, tlbelo) ? '1' : '0',
+              SYSREG_BFEXT(ASID, tlbehi),
+              SYSREG_BFEXT(VPN, tlbehi) >> 2,
+              SYSREG_BFEXT(PFN, tlbelo) >> 2,
+              SYSREG_BFEXT(AP, tlbelo),
+              SYSREG_BFEXT(SZ, tlbelo),
+              SYSREG_BFEXT(TLBELO_C, tlbelo) ? 'C' : ' ',
+              SYSREG_BFEXT(B, tlbelo) ? 'B' : ' ',
+              SYSREG_BFEXT(W, tlbelo) ? 'W' : ' ',
+              SYSREG_BFEXT(TLBELO_D, tlbelo) ? 'D' : ' ');
 
        sysreg_write(MMUCR, mmucr_save);
        sysreg_write(TLBEHI, tlbehi_save);
@@ -54,29 +56,33 @@ void dump_dtlb(void)
        unsigned int i;
 
        printk("ID  V G ASID VPN   PFN   AP SZ C B W D\n");
-       for (i = 0; i < 32; i++)
+       for (i = 0; i < NR_TLB_ENTRIES; i++)
                show_dtlb_entry(i);
 }
 
-static unsigned long last_mmucr;
-
-static inline void set_replacement_pointer(unsigned shift)
+static void update_dtlb(unsigned long address, pte_t pte)
 {
-       unsigned long mmucr, mmucr_save;
+       u32 tlbehi;
+       u32 mmucr;
 
-       mmucr = mmucr_save = sysreg_read(MMUCR);
+       /*
+        * We're not changing the ASID here, so no need to flush the
+        * pipeline.
+        */
+       tlbehi = sysreg_read(TLBEHI);
+       tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
+       tlbehi |= address & MMU_VPN_MASK;
+       tlbehi |= SYSREG_BIT(TLBEHI_V);
+       sysreg_write(TLBEHI, tlbehi);
 
        /* Does this mapping already exist? */
-       __asm__ __volatile__(
-               "       tlbs\n"
-               "       mfsr %0, %1"
-               : "=r"(mmucr)
-               : "i"(SYSREG_MMUCR));
+       __builtin_tlbs();
+       mmucr = sysreg_read(MMUCR);
 
        if (mmucr & SYSREG_BIT(MMUCR_N)) {
                /* Not found -- pick a not-recently-accessed entry */
-               unsigned long rp;
-               unsigned long tlbar = sysreg_read(TLBARLO);
+               unsigned int rp;
+               u32 tlbar = sysreg_read(TLBARLO);
 
                rp = 32 - fls(tlbar);
                if (rp == 32) {
@@ -84,30 +90,14 @@ static inline void set_replacement_pointer(unsigned shift)
                        sysreg_write(TLBARLO, -1L);
                }
 
-               mmucr &= 0x13;
-               mmucr |= (rp << shift);
-
+               mmucr = SYSREG_BFINS(DRP, rp, mmucr);
                sysreg_write(MMUCR, mmucr);
        }
 
-       last_mmucr = mmucr;
-}
-
-static void update_dtlb(unsigned long address, pte_t pte, unsigned long asid)
-{
-       unsigned long vpn;
-
-       vpn = (address & MMU_VPN_MASK) | _TLBEHI_VALID | asid;
-       sysreg_write(TLBEHI, vpn);
-       cpu_sync_pipeline();
-
-       set_replacement_pointer(14);
-
        sysreg_write(TLBELO, pte_val(pte) & _PAGE_FLAGS_HARDWARE_MASK);
 
        /* Let's go */
-       asm volatile("nop\n\ttlbw" : : : "memory");
-       cpu_sync_pipeline();
+       __builtin_tlbw();
 }
 
 void update_mmu_cache(struct vm_area_struct *vma,
@@ -120,39 +110,40 @@ void update_mmu_cache(struct vm_area_struct *vma,
                return;
 
        local_irq_save(flags);
-       update_dtlb(address, pte, get_asid());
+       update_dtlb(address, pte);
        local_irq_restore(flags);
 }
 
-void __flush_tlb_page(unsigned long asid, unsigned long page)
+static void __flush_tlb_page(unsigned long asid, unsigned long page)
 {
-       unsigned long mmucr, tlbehi;
+       u32 mmucr, tlbehi;
 
-       page |= asid;
-       sysreg_write(TLBEHI, page);
-       cpu_sync_pipeline();
-       asm volatile("tlbs");
+       /*
+        * Caller is responsible for masking out non-PFN bits in page
+        * and changing the current ASID if necessary. This means that
+        * we don't need to flush the pipeline after writing TLBEHI.
+        */
+       tlbehi = page | asid;
+       sysreg_write(TLBEHI, tlbehi);
+
+       __builtin_tlbs();
        mmucr = sysreg_read(MMUCR);
 
        if (!(mmucr & SYSREG_BIT(MMUCR_N))) {
-               unsigned long tlbarlo;
-               unsigned long entry;
+               unsigned int entry;
+               u32 tlbarlo;
 
                /* Clear the "valid" bit */
-               tlbehi = sysreg_read(TLBEHI);
-               tlbehi &= ~_TLBEHI_VALID;
                sysreg_write(TLBEHI, tlbehi);
-               cpu_sync_pipeline();
 
                /* mark the entry as "not accessed" */
-               entry = (mmucr >> 14) & 0x3f;
+               entry = SYSREG_BFEXT(DRP, mmucr);
                tlbarlo = sysreg_read(TLBARLO);
-               tlbarlo |= (0x80000000 >> entry);
+               tlbarlo |= (0x80000000UL >> entry);
                sysreg_write(TLBARLO, tlbarlo);
 
                /* update the entry with valid bit clear */
-               asm volatile("tlbw");
-               cpu_sync_pipeline();
+               __builtin_tlbw();
        }
 }
 
@@ -190,17 +181,22 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 
                local_irq_save(flags);
                size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
                if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */
                        mm->context = NO_CONTEXT;
                        if (mm == current->mm)
                                activate_context(mm);
                } else {
-                       unsigned long asid = mm->context & MMU_CONTEXT_ASID_MASK;
-                       unsigned long saved_asid = MMU_NO_ASID;
+                       unsigned long asid;
+                       unsigned long saved_asid;
+
+                       asid = mm->context & MMU_CONTEXT_ASID_MASK;
+                       saved_asid = MMU_NO_ASID;
 
                        start &= PAGE_MASK;
                        end += (PAGE_SIZE - 1);
                        end &= PAGE_MASK;
+
                        if (mm != current->mm) {
                                saved_asid = get_asid();
                                set_asid(asid);
@@ -218,33 +214,34 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 }
 
 /*
- * TODO: If this is only called for addresses > TASK_SIZE, we can probably
- * skip the ASID stuff and just use the Global bit...
+ * This function depends on the pages to be flushed having the G
+ * (global) bit set in their pte. This is true for all
+ * PAGE_KERNEL(_RO) pages.
  */
 void flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
        unsigned long flags;
        int size;
 
-       local_irq_save(flags);
        size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
        if (size > (MMU_DTLB_ENTRIES / 4)) { /* Too many entries to flush */
                flush_tlb_all();
        } else {
-               unsigned long asid = init_mm.context & MMU_CONTEXT_ASID_MASK;
-               unsigned long saved_asid = get_asid();
+               unsigned long asid;
+
+               local_irq_save(flags);
+               asid = get_asid();
 
                start &= PAGE_MASK;
                end += (PAGE_SIZE - 1);
                end &= PAGE_MASK;
-               set_asid(asid);
+
                while (start < end) {
                        __flush_tlb_page(asid, start);
                        start += PAGE_SIZE;
                }
-               set_asid(saved_asid);
+               local_irq_restore(flags);
        }
-       local_irq_restore(flags);
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
@@ -280,7 +277,7 @@ static void *tlb_start(struct seq_file *tlb, loff_t *pos)
 {
        static unsigned long tlb_index;
 
-       if (*pos >= 32)
+       if (*pos >= NR_TLB_ENTRIES)
                return NULL;
 
        tlb_index = 0;
@@ -291,7 +288,7 @@ static void *tlb_next(struct seq_file *tlb, void *v, loff_t *pos)
 {
        unsigned long *index = v;
 
-       if (*index >= 31)
+       if (*index >= NR_TLB_ENTRIES - 1)
                return NULL;
 
        ++*pos;
@@ -313,16 +310,16 @@ static int tlb_show(struct seq_file *tlb, void *v)
        if (*index == 0)
                seq_puts(tlb, "ID  V G ASID VPN   PFN   AP SZ C B W D\n");
 
-       BUG_ON(*index >= 32);
+       BUG_ON(*index >= NR_TLB_ENTRIES);
 
        local_irq_save(flags);
        mmucr_save = sysreg_read(MMUCR);
        tlbehi_save = sysreg_read(TLBEHI);
-       mmucr = mmucr_save & 0x13;
-       mmucr |= *index << 14;
+       mmucr = SYSREG_BFINS(DRP, *index, mmucr_save);
        sysreg_write(MMUCR, mmucr);
 
-       asm volatile("tlbr" : : : "memory");
+       /* TLBR might change the ASID */
+       __builtin_tlbr();
        cpu_sync_pipeline();
 
        tlbehi = sysreg_read(TLBEHI);
@@ -334,16 +331,18 @@ static int tlb_show(struct seq_file *tlb, void *v)
        local_irq_restore(flags);
 
        seq_printf(tlb, "%2lu: %c %c %02x   %05x %05x %o  %o  %c %c %c %c\n",
-              *index,
-              (tlbehi & 0x200)?'1':'0',
-              (tlbelo & 0x100)?'1':'0',
-              (tlbehi & 0xff),
-              (tlbehi >> 12), (tlbelo >> 12),
-              (tlbelo >> 4) & 7, (tlbelo >> 2) & 3,
-              (tlbelo & 0x200)?'1':'0',
-              (tlbelo & 0x080)?'1':'0',
-              (tlbelo & 0x001)?'1':'0',
-              (tlbelo & 0x002)?'1':'0');
+                  *index,
+                  SYSREG_BFEXT(TLBEHI_V, tlbehi) ? '1' : '0',
+                  SYSREG_BFEXT(G, tlbelo) ? '1' : '0',
+                  SYSREG_BFEXT(ASID, tlbehi),
+                  SYSREG_BFEXT(VPN, tlbehi) >> 2,
+                  SYSREG_BFEXT(PFN, tlbelo) >> 2,
+                  SYSREG_BFEXT(AP, tlbelo),
+                  SYSREG_BFEXT(SZ, tlbelo),
+                  SYSREG_BFEXT(TLBELO_C, tlbelo) ? '1' : '0',
+                  SYSREG_BFEXT(B, tlbelo) ? '1' : '0',
+                  SYSREG_BFEXT(W, tlbelo) ? '1' : '0',
+                  SYSREG_BFEXT(TLBELO_D, tlbelo) ? '1' : '0');
 
        return 0;
 }
index 107e492..5dc8f80 100644 (file)
@@ -146,6 +146,7 @@ config MATHEMU
 config COMPAT
        bool "Kernel support for 31 bit emulation"
        depends on 64BIT
+       select COMPAT_BINFMT_ELF
        help
          Select this option if you want to enable your system kernel to
          handle system-calls from ELF binaries for 31 bit ESA.  This option
@@ -312,6 +313,10 @@ config ARCH_SPARSEMEM_DEFAULT
 config ARCH_SELECT_MEMORY_MODEL
        def_bool y
 
+config ARCH_ENABLE_MEMORY_HOTPLUG
+       def_bool y
+       depends on SPARSEMEM
+
 source "mm/Kconfig"
 
 comment "I/O subsystem configuration"
@@ -344,6 +349,22 @@ config QDIO_DEBUG
 
          If unsure, say N.
 
+config CHSC_SCH
+       tristate "Support for CHSC subchannels"
+       help
+         This driver allows usage of CHSC subchannels. A CHSC subchannel
+         is usually present on LPAR only.
+         The driver creates a device /dev/chsc, which may be used to
+         obtain I/O configuration information about the machine and
+         to issue asynchronous chsc commands (DANGEROUS).
+         You will usually only want to use this interface on a special
+         LPAR designated for system management.
+
+         To compile this driver as a module, choose M here: the
+         module will be called chsc_sch.
+
+         If unsure, say N.
+
 comment "Misc"
 
 config IPL
index db3ae85..17a2636 100644 (file)
@@ -3,13 +3,11 @@
  *
  * Definitions and interface for Linux - z/VM Monitor Stream.
  *
- * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright IBM Corp. 2003, 2008
  *
  * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
 
-//#define APPLDATA_DEBUG                       /* Debug messages on/off */
-
 #define APPLDATA_MAX_REC_SIZE    4024  /* Maximum size of the */
                                        /* data buffer */
 #define APPLDATA_MAX_PROCS 100
 #define P_ERROR(x...)  printk(KERN_ERR MY_PRINT_NAME " error: " x)
 #define P_WARNING(x...)        printk(KERN_WARNING MY_PRINT_NAME " status: " x)
 
-#ifdef APPLDATA_DEBUG
-#define P_DEBUG(x...)   printk(KERN_DEBUG MY_PRINT_NAME " debug: " x)
-#else
-#define P_DEBUG(x...)   do {} while (0)
-#endif
-
 struct appldata_ops {
        struct list_head list;
        struct ctl_table_header *sysctl_header;
index ad40729..9cb3d92 100644 (file)
@@ -5,7 +5,7 @@
  * Exports appldata_register_ops() and appldata_unregister_ops() for the
  * data gathering modules.
  *
- * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright IBM Corp. 2003, 2008
  *
  * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
@@ -108,9 +108,6 @@ static LIST_HEAD(appldata_ops_list);
  */
 static void appldata_timer_function(unsigned long data)
 {
-       P_DEBUG("   -= Timer =-\n");
-       P_DEBUG("CPU: %i, expire_count: %i\n", smp_processor_id(),
-               atomic_read(&appldata_expire_count));
        if (atomic_dec_and_test(&appldata_expire_count)) {
                atomic_set(&appldata_expire_count, num_online_cpus());
                queue_work(appldata_wq, (struct work_struct *) data);
@@ -128,14 +125,11 @@ static void appldata_work_fn(struct work_struct *work)
        struct appldata_ops *ops;
        int i;
 
-       P_DEBUG("  -= Work Queue =-\n");
        i = 0;
        get_online_cpus();
        spin_lock(&appldata_ops_lock);
        list_for_each(lh, &appldata_ops_list) {
                ops = list_entry(lh, struct appldata_ops, list);
-               P_DEBUG("list_for_each loop: %i) active = %u, name = %s\n",
-                       ++i, ops->active, ops->name);
                if (ops->active == 1) {
                        ops->callback(ops->data);
                }
@@ -212,7 +206,6 @@ __appldata_vtimer_setup(int cmd)
                                                 0, 1);
                }
                appldata_timer_active = 1;
-               P_INFO("Monitoring timer started.\n");
                break;
        case APPLDATA_DEL_TIMER:
                for_each_online_cpu(i)
@@ -221,7 +214,6 @@ __appldata_vtimer_setup(int cmd)
                        break;
                appldata_timer_active = 0;
                atomic_set(&appldata_expire_count, num_online_cpus());
-               P_INFO("Monitoring timer stopped.\n");
                break;
        case APPLDATA_MOD_TIMER:
                per_cpu_interval = (u64) (appldata_interval*1000 /
@@ -313,10 +305,8 @@ appldata_interval_handler(ctl_table *ctl, int write, struct file *filp,
        }
        interval = 0;
        sscanf(buf, "%i", &interval);
-       if (interval <= 0) {
-               P_ERROR("Timer CPU interval has to be > 0!\n");
+       if (interval <= 0)
                return -EINVAL;
-       }
 
        get_online_cpus();
        spin_lock(&appldata_timer_lock);
@@ -324,9 +314,6 @@ appldata_interval_handler(ctl_table *ctl, int write, struct file *filp,
        __appldata_vtimer_setup(APPLDATA_MOD_TIMER);
        spin_unlock(&appldata_timer_lock);
        put_online_cpus();
-
-       P_INFO("Monitoring CPU interval set to %u milliseconds.\n",
-                interval);
 out:
        *lenp = len;
        *ppos += len;
@@ -406,23 +393,16 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
                        P_ERROR("START DIAG 0xDC for %s failed, "
                                "return code: %d\n", ops->name, rc);
                        module_put(ops->owner);
-               } else {
-                       P_INFO("Monitoring %s data enabled, "
-                               "DIAG 0xDC started.\n", ops->name);
+               } else
                        ops->active = 1;
-               }
        } else if ((buf[0] == '0') && (ops->active == 1)) {
                ops->active = 0;
                rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
                                (unsigned long) ops->data, ops->size,
                                ops->mod_lvl);
-               if (rc != 0) {
+               if (rc != 0)
                        P_ERROR("STOP DIAG 0xDC for %s failed, "
                                "return code: %d\n", ops->name, rc);
-               } else {
-                       P_INFO("Monitoring %s data disabled, "
-                               "DIAG 0xDC stopped.\n", ops->name);
-               }
                module_put(ops->owner);
        }
        spin_unlock(&appldata_ops_lock);
@@ -468,7 +448,6 @@ int appldata_register_ops(struct appldata_ops *ops)
        ops->sysctl_header = register_sysctl_table(ops->ctl_table);
        if (!ops->sysctl_header)
                goto out;
-       P_INFO("%s-ops registered!\n", ops->name);
        return 0;
 out:
        spin_lock(&appldata_ops_lock);
@@ -490,7 +469,6 @@ void appldata_unregister_ops(struct appldata_ops *ops)
        spin_unlock(&appldata_ops_lock);
        unregister_sysctl_table(ops->sysctl_header);
        kfree(ops->ctl_table);
-       P_INFO("%s-ops unregistered!\n", ops->name);
 }
 /********************** module-ops management <END> **************************/
 
@@ -553,14 +531,9 @@ static int __init appldata_init(void)
 {
        int i;
 
-       P_DEBUG("sizeof(parameter_list) = %lu\n",
-               sizeof(struct appldata_parameter_list));
-
        appldata_wq = create_singlethread_workqueue("appldata");
-       if (!appldata_wq) {
-               P_ERROR("Could not create work queue\n");
+       if (!appldata_wq)
                return -ENOMEM;
-       }
 
        get_online_cpus();
        for_each_online_cpu(i)
@@ -571,8 +544,6 @@ static int __init appldata_init(void)
        register_hotcpu_notifier(&appldata_nb);
 
        appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
-
-       P_DEBUG("Base interface initialized.\n");
        return 0;
 }
 
@@ -584,7 +555,9 @@ EXPORT_SYMBOL_GPL(appldata_register_ops);
 EXPORT_SYMBOL_GPL(appldata_unregister_ops);
 EXPORT_SYMBOL_GPL(appldata_diag);
 
+#ifdef CONFIG_SWAP
 EXPORT_SYMBOL_GPL(si_swapinfo);
+#endif
 EXPORT_SYMBOL_GPL(nr_threads);
 EXPORT_SYMBOL_GPL(nr_running);
 EXPORT_SYMBOL_GPL(nr_iowait);
index 51181cc..3ed56b7 100644 (file)
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
-#include <asm/io.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
+#include <asm/io.h>
 
 #include "appldata.h"
 
 
-#define MY_PRINT_NAME "appldata_mem"           /* for debug messages, etc. */
 #define P2K(x) ((x) << (PAGE_SHIFT - 10))      /* Converts #Pages to KB */
 
 /*
@@ -70,30 +69,6 @@ static struct appldata_mem_data {
 } __attribute__((packed)) appldata_mem_data;
 
 
-static inline void appldata_debug_print(struct appldata_mem_data *mem_data)
-{
-       P_DEBUG("--- MEM - RECORD ---\n");
-       P_DEBUG("pgpgin     = %8lu KB\n", mem_data->pgpgin);
-       P_DEBUG("pgpgout    = %8lu KB\n", mem_data->pgpgout);
-       P_DEBUG("pswpin     = %8lu Pages\n", mem_data->pswpin);
-       P_DEBUG("pswpout    = %8lu Pages\n", mem_data->pswpout);
-       P_DEBUG("pgalloc    = %8lu \n", mem_data->pgalloc);
-       P_DEBUG("pgfault    = %8lu \n", mem_data->pgfault);
-       P_DEBUG("pgmajfault = %8lu \n", mem_data->pgmajfault);
-       P_DEBUG("sharedram  = %8lu KB\n", mem_data->sharedram);
-       P_DEBUG("totalram   = %8lu KB\n", mem_data->totalram);
-       P_DEBUG("freeram    = %8lu KB\n", mem_data->freeram);
-       P_DEBUG("totalhigh  = %8lu KB\n", mem_data->totalhigh);
-       P_DEBUG("freehigh   = %8lu KB\n", mem_data->freehigh);
-       P_DEBUG("bufferram  = %8lu KB\n", mem_data->bufferram);
-       P_DEBUG("cached     = %8lu KB\n", mem_data->cached);
-       P_DEBUG("totalswap  = %8lu KB\n", mem_data->totalswap);
-       P_DEBUG("freeswap   = %8lu KB\n", mem_data->freeswap);
-       P_DEBUG("sync_count_1 = %u\n", mem_data->sync_count_1);
-       P_DEBUG("sync_count_2 = %u\n", mem_data->sync_count_2);
-       P_DEBUG("timestamp    = %lX\n", mem_data->timestamp);
-}
-
 /*
  * appldata_get_mem_data()
  *
@@ -140,9 +115,6 @@ static void appldata_get_mem_data(void *data)
 
        mem_data->timestamp = get_clock();
        mem_data->sync_count_2++;
-#ifdef APPLDATA_DEBUG
-       appldata_debug_print(mem_data);
-#endif
 }
 
 
@@ -164,17 +136,7 @@ static struct appldata_ops ops = {
  */
 static int __init appldata_mem_init(void)
 {
-       int rc;
-
-       P_DEBUG("sizeof(mem) = %lu\n", sizeof(struct appldata_mem_data));
-
-       rc = appldata_register_ops(&ops);
-       if (rc != 0) {
-               P_ERROR("Error registering ops, rc = %i\n", rc);
-       } else {
-               P_DEBUG("%s-ops registered!\n", ops.name);
-       }
-       return rc;
+       return appldata_register_ops(&ops);
 }
 
 /*
@@ -185,7 +147,6 @@ static int __init appldata_mem_init(void)
 static void __exit appldata_mem_exit(void)
 {
        appldata_unregister_ops(&ops);
-       P_DEBUG("%s-ops unregistered!\n", ops.name);
 }
 
 
index 4d83443..3b74655 100644 (file)
@@ -21,9 +21,6 @@
 #include "appldata.h"
 
 
-#define MY_PRINT_NAME  "appldata_net_sum"      /* for debug messages, etc. */
-
-
 /*
  * Network data
  *
@@ -60,26 +57,6 @@ static struct appldata_net_sum_data {
 } __attribute__((packed)) appldata_net_sum_data;
 
 
-static inline void appldata_print_debug(struct appldata_net_sum_data *net_data)
-{
-       P_DEBUG("--- NET - RECORD ---\n");
-
-       P_DEBUG("nr_interfaces = %u\n", net_data->nr_interfaces);
-       P_DEBUG("rx_packets    = %8lu\n", net_data->rx_packets);
-       P_DEBUG("tx_packets    = %8lu\n", net_data->tx_packets);
-       P_DEBUG("rx_bytes      = %8lu\n", net_data->rx_bytes);
-       P_DEBUG("tx_bytes      = %8lu\n", net_data->tx_bytes);
-       P_DEBUG("rx_errors     = %8lu\n", net_data->rx_errors);
-       P_DEBUG("tx_errors     = %8lu\n", net_data->tx_errors);
-       P_DEBUG("rx_dropped    = %8lu\n", net_data->rx_dropped);
-       P_DEBUG("tx_dropped    = %8lu\n", net_data->tx_dropped);
-       P_DEBUG("collisions    = %8lu\n", net_data->collisions);
-
-       P_DEBUG("sync_count_1 = %u\n", net_data->sync_count_1);
-       P_DEBUG("sync_count_2 = %u\n", net_data->sync_count_2);
-       P_DEBUG("timestamp    = %lX\n", net_data->timestamp);
-}
-
 /*
  * appldata_get_net_sum_data()
  *
@@ -135,9 +112,6 @@ static void appldata_get_net_sum_data(void *data)
 
        net_data->timestamp = get_clock();
        net_data->sync_count_2++;
-#ifdef APPLDATA_DEBUG
-       appldata_print_debug(net_data);
-#endif
 }
 
 
@@ -159,17 +133,7 @@ static struct appldata_ops ops = {
  */
 static int __init appldata_net_init(void)
 {
-       int rc;
-
-       P_DEBUG("sizeof(net) = %lu\n", sizeof(struct appldata_net_sum_data));
-
-       rc = appldata_register_ops(&ops);
-       if (rc != 0) {
-               P_ERROR("Error registering ops, rc = %i\n", rc);
-       } else {
-               P_DEBUG("%s-ops registered!\n", ops.name);
-       }
-       return rc;
+       return appldata_register_ops(&ops);
 }
 
 /*
@@ -180,7 +144,6 @@ static int __init appldata_net_init(void)
 static void __exit appldata_net_exit(void)
 {
        appldata_unregister_ops(&ops);
-       P_DEBUG("%s-ops unregistered!\n", ops.name);
 }
 
 
index 6b3eafe..eb44f9f 100644 (file)
@@ -89,44 +89,6 @@ static struct appldata_ops ops = {
 };
 
 
-static inline void appldata_print_debug(struct appldata_os_data *os_data)
-{
-       int a0, a1, a2, i;
-
-       P_DEBUG("--- OS - RECORD ---\n");
-       P_DEBUG("nr_threads   = %u\n", os_data->nr_threads);
-       P_DEBUG("nr_running   = %u\n", os_data->nr_running);
-       P_DEBUG("nr_iowait    = %u\n", os_data->nr_iowait);
-       P_DEBUG("avenrun(int) = %8x / %8x / %8x\n", os_data->avenrun[0],
-               os_data->avenrun[1], os_data->avenrun[2]);
-       a0 = os_data->avenrun[0];
-       a1 = os_data->avenrun[1];
-       a2 = os_data->avenrun[2];
-       P_DEBUG("avenrun(float) = %d.%02d / %d.%02d / %d.%02d\n",
-               LOAD_INT(a0), LOAD_FRAC(a0), LOAD_INT(a1), LOAD_FRAC(a1),
-               LOAD_INT(a2), LOAD_FRAC(a2));
-
-       P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus);
-       for (i = 0; i < os_data->nr_cpus; i++) {
-               P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, "
-                       "idle = %u, irq = %u, softirq = %u, iowait = %u, "
-                       "steal = %u\n",
-                               os_data->os_cpu[i].cpu_id,
-                               os_data->os_cpu[i].per_cpu_user,
-                               os_data->os_cpu[i].per_cpu_nice,
-                               os_data->os_cpu[i].per_cpu_system,
-                               os_data->os_cpu[i].per_cpu_idle,
-                               os_data->os_cpu[i].per_cpu_irq,
-                               os_data->os_cpu[i].per_cpu_softirq,
-                               os_data->os_cpu[i].per_cpu_iowait,
-                               os_data->os_cpu[i].per_cpu_steal);
-       }
-
-       P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1);
-       P_DEBUG("sync_count_2 = %u\n", os_data->sync_count_2);
-       P_DEBUG("timestamp    = %lX\n", os_data->timestamp);
-}
-
 /*
  * appldata_get_os_data()
  *
@@ -180,13 +142,10 @@ static void appldata_get_os_data(void *data)
                                           APPLDATA_START_INTERVAL_REC,
                                           (unsigned long) ops.data, new_size,
                                           ops.mod_lvl);
-                       if (rc != 0) {
+                       if (rc != 0)
                                P_ERROR("os: START NEW DIAG 0xDC failed, "
                                        "return code: %d, new size = %i\n", rc,
                                        new_size);
-                               P_INFO("os: stopping old record now\n");
-                       } else
-                               P_INFO("os: new record size = %i\n", new_size);
 
                        rc = appldata_diag(APPLDATA_RECORD_OS_ID,
                                           APPLDATA_STOP_REC,
@@ -204,9 +163,6 @@ static void appldata_get_os_data(void *data)
        }
        os_data->timestamp = get_clock();
        os_data->sync_count_2++;
-#ifdef APPLDATA_DEBUG
-       appldata_print_debug(os_data);
-#endif
 }
 
 
@@ -227,12 +183,9 @@ static int __init appldata_os_init(void)
                rc = -ENOMEM;
                goto out;
        }
-       P_DEBUG("max. sizeof(os) = %i, sizeof(os_cpu) = %lu\n", max_size,
-               sizeof(struct appldata_os_per_cpu));
 
        appldata_os_data = kzalloc(max_size, GFP_DMA);
        if (appldata_os_data == NULL) {
-               P_ERROR("No memory for %s!\n", ops.name);
                rc = -ENOMEM;
                goto out;
        }
@@ -240,17 +193,12 @@ static int __init appldata_os_init(void)
        appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu);
        appldata_os_data->cpu_offset   = offsetof(struct appldata_os_data,
                                                        os_cpu);
-       P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset);
 
        ops.data = appldata_os_data;
        ops.callback  = &appldata_get_os_data;
        rc = appldata_register_ops(&ops);
-       if (rc != 0) {
-               P_ERROR("Error registering ops, rc = %i\n", rc);
+       if (rc != 0)
                kfree(appldata_os_data);
-       } else {
-               P_DEBUG("%s-ops registered!\n", ops.name);
-       }
 out:
        return rc;
 }
@@ -264,7 +212,6 @@ static void __exit appldata_os_exit(void)
 {
        appldata_unregister_ops(&ops);
        kfree(appldata_os_data);
-       P_DEBUG("%s-ops unregistered!\n", ops.name);
 }
 
 
index 9992f95..0ef9829 100644 (file)
@@ -296,6 +296,10 @@ static inline int crypt_s390_func_available(int func)
        unsigned char status[16];
        int ret;
 
+       /* check if CPACF facility (bit 17) is available */
+       if (!(stfl() & 1ULL << (31 - 17)))
+               return 0;
+
        switch (func & CRYPT_S390_OP_MASK) {
        case CRYPT_S390_KM:
                ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0);
index 0cfefdd..6a4300b 100644 (file)
@@ -185,11 +185,8 @@ static int __init prng_init(void)
        prng_seed(16);
 
        ret = misc_register(&prng_dev);
-       if (ret) {
-               printk(KERN_WARNING
-                      "Could not register misc device for PRNG.\n");
+       if (ret)
                goto out_buf;
-       }
        return 0;
 
 out_buf:
index 4b010ff..7383781 100644 (file)
@@ -150,33 +150,24 @@ static ssize_t hypfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
                              unsigned long nr_segs, loff_t offset)
 {
        char *data;
-       size_t len;
+       ssize_t ret;
        struct file *filp = iocb->ki_filp;
        /* XXX: temporary */
        char __user *buf = iov[0].iov_base;
        size_t count = iov[0].iov_len;
 
-       if (nr_segs != 1) {
-               count = -EINVAL;
-               goto out;
-       }
+       if (nr_segs != 1)
+               return -EINVAL;
 
        data = filp->private_data;
-       len = strlen(data);
-       if (offset > len) {
-               count = 0;
-               goto out;
-       }
-       if (count > len - offset)
-               count = len - offset;
-       if (copy_to_user(buf, data + offset, count)) {
-               count = -EFAULT;
-               goto out;
-       }
-       iocb->ki_pos += count;
+       ret = simple_read_from_buffer(buf, count, &offset, data, strlen(data));
+       if (ret <= 0)
+               return ret;
+
+       iocb->ki_pos += ret;
        file_accessed(filp);
-out:
-       return count;
+
+       return ret;
 }
 static ssize_t hypfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
                              unsigned long nr_segs, loff_t offset)
index 6302f50..50f657e 100644 (file)
@@ -7,9 +7,14 @@
 #
 CFLAGS_smp.o   := -Wno-nonnull
 
+#
+# Pass UTS_MACHINE for user_regset definition
+#
+CFLAGS_ptrace.o                += -DUTS_MACHINE='"$(UTS_MACHINE)"'
+
 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 \
-           s390_ext.o debug.o irq.o ipl.o dis.o diag.o
+           s390_ext.o debug.o irq.o ipl.o dis.o diag.o mem_detect.o
 
 obj-y  += $(if $(CONFIG_64BIT),entry64.o,entry.o)
 obj-y  += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
@@ -23,7 +28,7 @@ obj-$(CONFIG_AUDIT)           += audit.o
 compat-obj-$(CONFIG_AUDIT)     += compat_audit.o
 obj-$(CONFIG_COMPAT)           += compat_linux.o compat_signal.o \
                                        compat_wrapper.o compat_exec_domain.o \
-                                       binfmt_elf32.o $(compat-obj-y)
+                                       $(compat-obj-y)
 
 obj-$(CONFIG_VIRT_TIMER)       += vtime.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c
deleted file mode 100644 (file)
index 3e1c315..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Support for 32-bit Linux for S390 ELF binaries.
- *
- * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Gerhard Tonn (ton@de.ibm.com)
- *
- * Heavily inspired by the 32-bit Sparc compat code which is
- * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
- * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek   (jj@ultra.linux.cz)
- */
-
-#define __ASMS390_ELF_H
-
-#include <linux/time.h>
-
-/*
- * These are used to set parameters in the core dumps.
- */
-#define ELF_CLASS      ELFCLASS32
-#define ELF_DATA       ELFDATA2MSB
-#define ELF_ARCH       EM_S390
-
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) \
-       (((x)->e_machine == EM_S390 || (x)->e_machine == EM_S390_OLD) \
-         && (x)->e_ident[EI_CLASS] == ELF_CLASS)
-
-/* ELF register definitions */
-#define NUM_GPRS      16
-#define NUM_FPRS      16
-#define NUM_ACRS      16    
-
-/* For SVR4/S390 the function pointer to be registered with `atexit` is
-   passed in R14. */
-#define ELF_PLAT_INIT(_r, load_addr) \
-       do { \
-               _r->gprs[14] = 0; \
-       } while(0)
-
-#define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE       4096
-
-/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
-   use of this is to invoke "./ld.so someprog" to test out a new version of
-   the loader.  We need to make sure that it is out of the way of the program
-   that it will "exec", and that there is sufficient room for the brk.  */
-
-#define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
-
-/* Wow, the "main" arch needs arch dependent functions too.. :) */
-
-/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
-   now struct_user_regs, they are different) */
-
-#define ELF_CORE_COPY_REGS(pr_reg, regs) dump_regs32(regs, &pr_reg);
-
-#define ELF_CORE_COPY_TASK_REGS(tsk, regs) dump_task_regs32(tsk, regs)
-
-#define ELF_CORE_COPY_FPREGS(tsk, fpregs) dump_task_fpu(tsk, fpregs)
-
-/* This yields a mask that user programs can use to figure out what
-   instruction set this CPU supports. */
-
-#define ELF_HWCAP (0)
-
-/* This yields a string that ld.so will use to load implementation
-   specific libraries for optimization.  This is more specific in
-   intent than poking at uname or /proc/cpuinfo.
-
-   For the moment, we have only optimizations for the Intel generations,
-   but that could change... */
-
-#define ELF_PLATFORM (NULL)
-
-#define SET_PERSONALITY(ex, ibcs2)                     \
-do {                                                   \
-       if (ibcs2)                                      \
-               set_personality(PER_SVR4);              \
-       else if (current->personality != PER_LINUX32)   \
-               set_personality(PER_LINUX);             \
-       set_thread_flag(TIF_31BIT);                     \
-} while (0)
-
-#include "compat_linux.h"
-
-typedef _s390_fp_regs32 elf_fpregset_t;
-
-typedef struct
-{
-       
-       _psw_t32        psw;
-       __u32           gprs[__NUM_GPRS]; 
-       __u32           acrs[__NUM_ACRS]; 
-       __u32           orig_gpr2;
-} s390_regs32;
-typedef s390_regs32 elf_gregset_t;
-
-static inline int dump_regs32(struct pt_regs *ptregs, elf_gregset_t *regs)
-{
-       int i;
-
-       memcpy(&regs->psw.mask, &ptregs->psw.mask, 4);
-       memcpy(&regs->psw.addr, (char *)&ptregs->psw.addr + 4, 4);
-       for (i = 0; i < NUM_GPRS; i++)
-               regs->gprs[i] = ptregs->gprs[i];
-       save_access_regs(regs->acrs);
-       regs->orig_gpr2 = ptregs->orig_gpr2;
-       return 1;
-}
-
-static inline int dump_task_regs32(struct task_struct *tsk, elf_gregset_t *regs)
-{
-       struct pt_regs *ptregs = task_pt_regs(tsk);
-       int i;
-
-       memcpy(&regs->psw.mask, &ptregs->psw.mask, 4);
-       memcpy(&regs->psw.addr, (char *)&ptregs->psw.addr + 4, 4);
-       for (i = 0; i < NUM_GPRS; i++)
-               regs->gprs[i] = ptregs->gprs[i];
-       memcpy(regs->acrs, tsk->thread.acrs, sizeof(regs->acrs));
-       regs->orig_gpr2 = ptregs->orig_gpr2;
-       return 1;
-}
-
-static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
-{
-       if (tsk == current)
-               save_fp_regs((s390_fp_regs *) fpregs);
-       else
-               memcpy(fpregs, &tsk->thread.fp_regs, sizeof(elf_fpregset_t));
-       return 1;
-}
-
-#include <asm/processor.h>
-#include <asm/pgalloc.h>
-#include <linux/module.h>
-#include <linux/elfcore.h>
-#include <linux/binfmts.h>
-#include <linux/compat.h>
-
-#define elf_prstatus elf_prstatus32
-struct elf_prstatus32
-{
-       struct elf_siginfo pr_info;     /* Info associated with signal */
-       short   pr_cursig;              /* Current signal */
-       u32     pr_sigpend;     /* Set of pending signals */
-       u32     pr_sighold;     /* Set of held signals */
-       pid_t   pr_pid;
-       pid_t   pr_ppid;
-       pid_t   pr_pgrp;
-       pid_t   pr_sid;
-       struct compat_timeval pr_utime; /* User time */
-       struct compat_timeval pr_stime; /* System time */
-       struct compat_timeval pr_cutime;        /* Cumulative user time */
-       struct compat_timeval pr_cstime;        /* Cumulative system time */
-       elf_gregset_t pr_reg;   /* GP registers */
-       int pr_fpvalid;         /* True if math co-processor being used.  */
-};
-
-#define elf_prpsinfo elf_prpsinfo32
-struct elf_prpsinfo32
-{
-       char    pr_state;       /* numeric process state */
-       char    pr_sname;       /* char for pr_state */
-       char    pr_zomb;        /* zombie */
-       char    pr_nice;        /* nice val */
-       u32     pr_flag;        /* flags */
-       u16     pr_uid;
-       u16     pr_gid;
-       pid_t   pr_pid, pr_ppid, pr_pgrp, pr_sid;
-       /* Lots missing */
-       char    pr_fname[16];   /* filename of executable */
-       char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
-};
-
-#include <linux/highuid.h>
-
-/*
-#define init_elf_binfmt init_elf32_binfmt
-*/
-
-#undef start_thread
-#define start_thread                    start_thread31 
-
-static inline void start_thread31(struct pt_regs *regs, unsigned long new_psw,
-                                 unsigned long new_stackp)
-{
-       set_fs(USER_DS);
-       regs->psw.mask  = psw_user32_bits;
-       regs->psw.addr  = new_psw;
-       regs->gprs[15]  = new_stackp;
-       crst_table_downgrade(current->mm, 1UL << 31);
-}
-
-MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux for S390 binaries,"
-                   " Copyright 2000 IBM Corporation"); 
-MODULE_AUTHOR("Gerhard Tonn <ton@de.ibm.com>");
-
-#undef MODULE_DESCRIPTION
-#undef MODULE_AUTHOR
-
-#undef cputime_to_timeval
-#define cputime_to_timeval cputime_to_compat_timeval
-static inline void
-cputime_to_compat_timeval(const cputime_t cputime, struct compat_timeval *value)
-{
-       value->tv_usec = cputime % 1000000;
-       value->tv_sec = cputime / 1000000;
-}
-
-#include "../../../fs/binfmt_elf.c"
-
index 419aef9..cde81fa 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _PTRACE32_H
 #define _PTRACE32_H
 
-#include "compat_linux.h"  /* needed for _psw_t32 */
+#include "compat_linux.h"  /* needed for psw_compat_t */
 
 typedef struct {
        __u32 cr[3];
@@ -38,7 +38,7 @@ typedef struct {
 
 struct user_regs_struct32
 {
-       _psw_t32 psw;
+       psw_compat_t psw;
        u32 gprs[NUM_GPRS];
        u32 acrs[NUM_ACRS];
        u32 orig_gpr2;
index c93d129..d80fcd4 100644 (file)
@@ -1079,7 +1079,6 @@ __init debug_init(void)
        s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
        mutex_lock(&debug_mutex);
        debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
-       printk(KERN_INFO "debug: Initialization complete\n");
        initialized = 1;
        mutex_unlock(&debug_mutex);
 
@@ -1193,7 +1192,6 @@ debug_get_uint(char *buf)
        for(; isspace(*buf); buf++);
        rc = simple_strtoul(buf, &buf, 10);
        if(*buf){
-               printk("debug: no integer specified!\n");
                rc = -EINVAL;
        }
        return rc;
@@ -1340,19 +1338,12 @@ static void debug_flush(debug_info_t* id, int area)
                                memset(id->areas[i][j], 0, PAGE_SIZE);
                        }
                }
-                printk(KERN_INFO "debug: %s: all areas flushed\n",id->name);
         } else if(area >= 0 && area < id->nr_areas) {
                 id->active_entries[area] = 0;
                id->active_pages[area] = 0;
                for(i = 0; i < id->pages_per_area; i++) {
                        memset(id->areas[area][i],0,PAGE_SIZE);
                }
-                printk(KERN_INFO "debug: %s: area %i has been flushed\n",
-                        id->name, area);
-        } else {
-                printk(KERN_INFO
-                      "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
-                        id->name, area, 0, id->nr_areas-1);
         }
         spin_unlock_irqrestore(&id->lock,flags);
 }
index d0e0968..2a2ca26 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/pfn.h>
 #include <linux/uaccess.h>
+#include <asm/ebcdic.h>
 #include <asm/ipl.h>
 #include <asm/lowcore.h>
 #include <asm/processor.h>
 /*
  * Create a Kernel NSS if the SAVESYS= parameter is defined
  */
-#define DEFSYS_CMD_SIZE                96
+#define DEFSYS_CMD_SIZE                128
 #define SAVESYS_CMD_SIZE       32
 
 char kernel_nss_name[NSS_NAME_SIZE + 1];
 
+static void __init setup_boot_command_line(void);
+
+
 #ifdef CONFIG_SHARED_KERNEL
+int __init savesys_ipl_nss(char *cmd, const int cmdlen);
+
+asm(
+       "       .section .init.text,\"ax\",@progbits\n"
+       "       .align  4\n"
+       "       .type   savesys_ipl_nss, @function\n"
+       "savesys_ipl_nss:\n"
+#ifdef CONFIG_64BIT
+       "       stmg    6,15,48(15)\n"
+       "       lgr     14,3\n"
+       "       sam31\n"
+       "       diag    2,14,0x8\n"
+       "       sam64\n"
+       "       lgr     2,14\n"
+       "       lmg     6,15,48(15)\n"
+#else
+       "       stm     6,15,24(15)\n"
+       "       lr      14,3\n"
+       "       diag    2,14,0x8\n"
+       "       lr      2,14\n"
+       "       lm      6,15,24(15)\n"
+#endif
+       "       br      14\n"
+       "       .size   savesys_ipl_nss, .-savesys_ipl_nss\n");
+
 static noinline __init void create_kernel_nss(void)
 {
        unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
@@ -39,6 +68,7 @@ static noinline __init void create_kernel_nss(void)
        unsigned int sinitrd_pfn, einitrd_pfn;
 #endif
        int response;
+       size_t len;
        char *savesys_ptr;
        char upper_command_line[COMMAND_LINE_SIZE];
        char defsys_cmd[DEFSYS_CMD_SIZE];
@@ -49,8 +79,8 @@ static noinline __init void create_kernel_nss(void)
                return;
 
        /* Convert COMMAND_LINE to upper case */
-       for (i = 0; i < strlen(COMMAND_LINE); i++)
-               upper_command_line[i] = toupper(COMMAND_LINE[i]);
+       for (i = 0; i < strlen(boot_command_line); i++)
+               upper_command_line[i] = toupper(boot_command_line[i]);
 
        savesys_ptr = strstr(upper_command_line, "SAVESYS=");
 
@@ -83,7 +113,8 @@ static noinline __init void create_kernel_nss(void)
        }
 #endif
 
-       sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size);
+       sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK PARMREGS=0-13",
+               defsys_cmd, min_size);
        sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
                kernel_nss_name, kernel_nss_name);
 
@@ -94,13 +125,24 @@ static noinline __init void create_kernel_nss(void)
                return;
        }
 
-       __cpcmd(savesys_cmd, NULL, 0, &response);
+       len = strlen(savesys_cmd);
+       ASCEBC(savesys_cmd, len);
+       response = savesys_ipl_nss(savesys_cmd, len);
 
-       if (response != strlen(savesys_cmd)) {
+       /* On success: response is equal to the command size,
+        *             max SAVESYS_CMD_SIZE
+        * On error: response contains the numeric portion of cp error message.
+        *           for SAVESYS it will be >= 263
+        */
+       if (response > SAVESYS_CMD_SIZE) {
                kernel_nss_name[0] = '\0';
                return;
        }
 
+       /* re-setup boot command line with new ipl vm parms */
+       ipl_update_parameters();
+       setup_boot_command_line();
+
        ipl_flags = IPL_NSS_VALID;
 }
 
@@ -141,109 +183,11 @@ static noinline __init void detect_machine_type(void)
        if (cpuinfo->cpu_id.version == 0xff)
                machine_flags |= MACHINE_FLAG_VM;
 
-       /* Running on a P/390 ? */
-       if (cpuinfo->cpu_id.machine == 0x7490)
-               machine_flags |= MACHINE_FLAG_P390;
-
        /* Running under KVM ? */
        if (cpuinfo->cpu_id.version == 0xfe)
                machine_flags |= MACHINE_FLAG_KVM;
 }
 
-#ifdef CONFIG_64BIT
-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 + 1;
-       return 0;
-}
-#else
-static inline int memory_fast_detect(void)
-{
-       return -ENOSYS;
-}
-#endif
-
-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)
-#define ADDR2G         (1UL << 31)
-
-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;
-                       if (memsize && addr >= memsize)
-                               break;
-#ifndef CONFIG_64BIT
-                       if (addr == ADDR2G)
-                               break;
-#endif
-                       cc = __tprot(addr);
-               }
-
-               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
-                * if storage size is unknown.
-                */
-               if (cc == -1UL && !memsize)
-                       break;
-               if (memsize && addr >= memsize)
-                       break;
-       }
-}
-
 static __init void early_pgm_check_handler(void)
 {
        unsigned long addr;
@@ -380,23 +324,61 @@ static __init void detect_machine_facilities(void)
 #endif
 }
 
+static __init void rescue_initrd(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+       /*
+        * Move the initrd right behind the bss section in case it starts
+        * within the bss section. So we don't overwrite it when the bss
+        * section gets cleared.
+        */
+       if (!INITRD_START || !INITRD_SIZE)
+               return;
+       if (INITRD_START >= (unsigned long) __bss_stop)
+               return;
+       memmove(__bss_stop, (void *) INITRD_START, INITRD_SIZE);
+       INITRD_START = (unsigned long) __bss_stop;
+#endif
+}
+
+/* Set up boot command line */
+static void __init setup_boot_command_line(void)
+{
+       char *parm = NULL;
+
+       /* copy arch command line */
+       strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
+       boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0;
+
+       /* append IPL PARM data to the boot command line */
+       if (MACHINE_IS_VM) {
+               parm = boot_command_line + strlen(boot_command_line);
+               *parm++ = ' ';
+               get_ipl_vmparm(parm);
+               if (parm[0] == '=')
+                       memmove(boot_command_line, parm + 1, strlen(parm));
+       }
+}
+
+
 /*
  * 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 long memsize;
-
        ipl_save_parameters();
+       rescue_initrd();
        clear_bss_section();
        init_kernel_storage_key();
        lockdep_init();
        lockdep_off();
-       detect_machine_type();
-       create_kernel_nss();
        sort_main_extable();
        setup_lowcore_early();
+       detect_machine_type();
+       ipl_update_parameters();
+       setup_boot_command_line();
+       create_kernel_nss();
        detect_mvpg();
        detect_ieee();
        detect_csp();
@@ -404,18 +386,7 @@ void __init startup_init(void)
        detect_diag44();
        detect_machine_facilities();
        setup_hpage();
-       sclp_read_info_early();
        sclp_facilities_detect();
-       memsize = sclp_memory_detect();
-#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
-       if (memory_fast_detect() < 0)
-               find_memory_chunks((unsigned long) memsize);
+       detect_memory_layout(memory_chunk);
        lockdep_on();
 }
index 5325424..54b2779 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/ctype.h>
+#include <linux/fs.h>
 #include <asm/ipl.h>
 #include <asm/smp.h>
 #include <asm/setup.h>
@@ -22,6 +23,7 @@
 #include <asm/ebcdic.h>
 #include <asm/reset.h>
 #include <asm/sclp.h>
+#include <asm/setup.h>
 
 #define IPL_PARM_BLOCK_VERSION 0
 
@@ -121,6 +123,7 @@ enum ipl_method {
        REIPL_METHOD_FCP_RO_VM,
        REIPL_METHOD_FCP_DUMP,
        REIPL_METHOD_NSS,
+       REIPL_METHOD_NSS_DIAG,
        REIPL_METHOD_DEFAULT,
 };
 
@@ -134,14 +137,15 @@ enum dump_method {
 
 static int diag308_set_works = 0;
 
+static struct ipl_parameter_block ipl_block;
+
 static int reipl_capabilities = IPL_TYPE_UNKNOWN;
 
 static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
 static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT;
 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 struct ipl_parameter_block *reipl_block_nss;
 
 static int dump_capabilities = DUMP_TYPE_NONE;
 static enum dump_type dump_type = DUMP_TYPE_NONE;
@@ -263,6 +267,56 @@ static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
 
 static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
 
+/* VM IPL PARM routines */
+static void reipl_get_ascii_vmparm(char *dest,
+                                  const struct ipl_parameter_block *ipb)
+{
+       int i;
+       int len = 0;
+       char has_lowercase = 0;
+
+       if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
+           (ipb->ipl_info.ccw.vm_parm_len > 0)) {
+
+               len = ipb->ipl_info.ccw.vm_parm_len;
+               memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
+               /* If at least one character is lowercase, we assume mixed
+                * case; otherwise we convert everything to lowercase.
+                */
+               for (i = 0; i < len; i++)
+                       if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
+                           (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
+                           (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
+                               has_lowercase = 1;
+                               break;
+                       }
+               if (!has_lowercase)
+                       EBC_TOLOWER(dest, len);
+               EBCASC(dest, len);
+       }
+       dest[len] = 0;
+}
+
+void get_ipl_vmparm(char *dest)
+{
+       if (diag308_set_works && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
+               reipl_get_ascii_vmparm(dest, &ipl_block);
+       else
+               dest[0] = 0;
+}
+
+static ssize_t ipl_vm_parm_show(struct kobject *kobj,
+                               struct kobj_attribute *attr, char *page)
+{
+       char parm[DIAG308_VMPARM_SIZE + 1] = {};
+
+       get_ipl_vmparm(parm);
+       return sprintf(page, "%s\n", parm);
+}
+
+static struct kobj_attribute sys_ipl_vm_parm_attr =
+       __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
+
 static ssize_t sys_ipl_device_show(struct kobject *kobj,
                                   struct kobj_attribute *attr, char *page)
 {
@@ -285,14 +339,8 @@ static struct kobj_attribute sys_ipl_device_attr =
 static ssize_t ipl_parameter_read(struct kobject *kobj, struct bin_attribute *attr,
                                  char *buf, loff_t off, size_t count)
 {
-       unsigned int size = IPL_PARMBLOCK_SIZE;
-
-       if (off > size)
-               return 0;
-       if (off + count > size)
-               count = size - off;
-       memcpy(buf, (void *)IPL_PARMBLOCK_START + off, count);
-       return count;
+       return memory_read_from_buffer(buf, count, &off, IPL_PARMBLOCK_START,
+                                       IPL_PARMBLOCK_SIZE);
 }
 
 static struct bin_attribute ipl_parameter_attr = {
@@ -310,12 +358,7 @@ static ssize_t ipl_scp_data_read(struct kobject *kobj, struct bin_attribute *att
        unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len;
        void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data;
 
-       if (off > size)
-               return 0;
-       if (off + count > size)
-               count = size - off;
-       memcpy(buf, scp_data + off, count);
-       return count;
+       return memory_read_from_buffer(buf, count, &off, scp_data, size);
 }
 
 static struct bin_attribute ipl_scp_data_attr = {
@@ -370,15 +413,27 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
 static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
        __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
 
-static struct attribute *ipl_ccw_attrs[] = {
+static struct attribute *ipl_ccw_attrs_vm[] = {
        &sys_ipl_type_attr.attr,
        &sys_ipl_device_attr.attr,
        &sys_ipl_ccw_loadparm_attr.attr,
+       &sys_ipl_vm_parm_attr.attr,
        NULL,
 };
 
-static struct attribute_group ipl_ccw_attr_group = {
-       .attrs = ipl_ccw_attrs,
+static struct attribute *ipl_ccw_attrs_lpar[] = {
+       &sys_ipl_type_attr.attr,
+       &sys_ipl_device_attr.attr,
+       &sys_ipl_ccw_loadparm_attr.attr,
+       NULL,
+};
+
+static struct attribute_group ipl_ccw_attr_group_vm = {
+       .attrs = ipl_ccw_attrs_vm,
+};
+
+static struct attribute_group ipl_ccw_attr_group_lpar = {
+       .attrs = ipl_ccw_attrs_lpar
 };
 
 /* NSS ipl device attributes */
@@ -388,6 +443,8 @@ 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,
+       &sys_ipl_ccw_loadparm_attr.attr,
+       &sys_ipl_vm_parm_attr.attr,
        NULL,
 };
 
@@ -450,7 +507,12 @@ static int __init ipl_init(void)
        }
        switch (ipl_info.type) {
        case IPL_TYPE_CCW:
-               rc = sysfs_create_group(&ipl_kset->kobj, &ipl_ccw_attr_group);
+               if (MACHINE_IS_VM)
+                       rc = sysfs_create_group(&ipl_kset->kobj,
+                                               &ipl_ccw_attr_group_vm);
+               else
+                       rc = sysfs_create_group(&ipl_kset->kobj,
+                                               &ipl_ccw_attr_group_lpar);
                break;
        case IPL_TYPE_FCP:
        case IPL_TYPE_FCP_DUMP:
@@ -481,6 +543,83 @@ static struct shutdown_action __refdata ipl_action = {
  * reipl shutdown action: Reboot Linux on shutdown.
  */
 
+/* VM IPL PARM attributes */
+static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
+                                         char *page)
+{
+       char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
+
+       reipl_get_ascii_vmparm(vmparm, ipb);
+       return sprintf(page, "%s\n", vmparm);
+}
+
+static ssize_t reipl_generic_vmparm_store(struct ipl_parameter_block *ipb,
+                                         size_t vmparm_max,
+                                         const char *buf, size_t len)
+{
+       int i, ip_len;
+
+       /* ignore trailing newline */
+       ip_len = len;
+       if ((len > 0) && (buf[len - 1] == '\n'))
+               ip_len--;
+
+       if (ip_len > vmparm_max)
+               return -EINVAL;
+
+       /* parm is used to store kernel options, check for common chars */
+       for (i = 0; i < ip_len; i++)
+               if (!(isalnum(buf[i]) || isascii(buf[i]) || isprint(buf[i])))
+                       return -EINVAL;
+
+       memset(ipb->ipl_info.ccw.vm_parm, 0, DIAG308_VMPARM_SIZE);
+       ipb->ipl_info.ccw.vm_parm_len = ip_len;
+       if (ip_len > 0) {
+               ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
+               memcpy(ipb->ipl_info.ccw.vm_parm, buf, ip_len);
+               ASCEBC(ipb->ipl_info.ccw.vm_parm, ip_len);
+       } else {
+               ipb->ipl_info.ccw.vm_flags &= ~DIAG308_VM_FLAGS_VP_VALID;
+       }
+
+       return len;
+}
+
+/* NSS wrapper */
+static ssize_t reipl_nss_vmparm_show(struct kobject *kobj,
+                                    struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_vmparm_show(reipl_block_nss, page);
+}
+
+static ssize_t reipl_nss_vmparm_store(struct kobject *kobj,
+                                     struct kobj_attribute *attr,
+                                     const char *buf, size_t len)
+{
+       return reipl_generic_vmparm_store(reipl_block_nss, 56, buf, len);
+}
+
+/* CCW wrapper */
+static ssize_t reipl_ccw_vmparm_show(struct kobject *kobj,
+                                    struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_vmparm_show(reipl_block_ccw, page);
+}
+
+static ssize_t reipl_ccw_vmparm_store(struct kobject *kobj,
+                                     struct kobj_attribute *attr,
+                                     const char *buf, size_t len)
+{
+       return reipl_generic_vmparm_store(reipl_block_ccw, 64, buf, len);
+}
+
+static struct kobj_attribute sys_reipl_nss_vmparm_attr =
+       __ATTR(parm, S_IRUGO | S_IWUSR, reipl_nss_vmparm_show,
+                                       reipl_nss_vmparm_store);
+static struct kobj_attribute sys_reipl_ccw_vmparm_attr =
+       __ATTR(parm, S_IRUGO | S_IWUSR, reipl_ccw_vmparm_show,
+                                       reipl_ccw_vmparm_store);
+
 /* FCP reipl device attributes */
 
 DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
@@ -513,27 +652,26 @@ static struct attribute_group reipl_fcp_attr_group = {
 DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
        reipl_block_ccw->ipl_info.ccw.devno);
 
-static void reipl_get_ascii_loadparm(char *loadparm)
+static void reipl_get_ascii_loadparm(char *loadparm,
+                                    struct ipl_parameter_block *ibp)
 {
-       memcpy(loadparm, &reipl_block_ccw->ipl_info.ccw.load_param,
-              LOADPARM_LEN);
+       memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN);
        EBCASC(loadparm, LOADPARM_LEN);
        loadparm[LOADPARM_LEN] = 0;
        strstrip(loadparm);
 }
 
-static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
-                                      struct kobj_attribute *attr, char *page)
+static ssize_t reipl_generic_loadparm_show(struct ipl_parameter_block *ipb,
+                                          char *page)
 {
        char buf[LOADPARM_LEN + 1];
 
-       reipl_get_ascii_loadparm(buf);
+       reipl_get_ascii_loadparm(buf, ipb);
        return sprintf(page, "%s\n", buf);
 }
 
-static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
-                                       struct kobj_attribute *attr,
-                                       const char *buf, size_t len)
+static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
+                                           const char *buf, size_t len)
 {
        int i, lp_len;
 
@@ -552,35 +690,128 @@ static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
                return -EINVAL;
        }
        /* initialize loadparm with blanks */
-       memset(&reipl_block_ccw->ipl_info.ccw.load_param, ' ', LOADPARM_LEN);
+       memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN);
        /* copy and convert to ebcdic */
-       memcpy(&reipl_block_ccw->ipl_info.ccw.load_param, buf, lp_len);
-       ASCEBC(reipl_block_ccw->ipl_info.ccw.load_param, LOADPARM_LEN);
+       memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len);
+       ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN);
        return len;
 }
 
+/* NSS wrapper */
+static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
+                                      struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_loadparm_show(reipl_block_nss, page);
+}
+
+static ssize_t reipl_nss_loadparm_store(struct kobject *kobj,
+                                       struct kobj_attribute *attr,
+                                       const char *buf, size_t len)
+{
+       return reipl_generic_loadparm_store(reipl_block_nss, buf, len);
+}
+
+/* CCW wrapper */
+static ssize_t reipl_ccw_loadparm_show(struct kobject *kobj,
+                                      struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_loadparm_show(reipl_block_ccw, page);
+}
+
+static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
+                                       struct kobj_attribute *attr,
+                                       const char *buf, size_t len)
+{
+       return reipl_generic_loadparm_store(reipl_block_ccw, buf, len);
+}
+
 static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
-       __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
-              reipl_ccw_loadparm_store);
+       __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
+                                           reipl_ccw_loadparm_store);
 
-static struct attribute *reipl_ccw_attrs[] = {
+static struct attribute *reipl_ccw_attrs_vm[] = {
        &sys_reipl_ccw_device_attr.attr,
        &sys_reipl_ccw_loadparm_attr.attr,
+       &sys_reipl_ccw_vmparm_attr.attr,
        NULL,
 };
 
-static struct attribute_group reipl_ccw_attr_group = {
+static struct attribute *reipl_ccw_attrs_lpar[] = {
+       &sys_reipl_ccw_device_attr.attr,
+       &sys_reipl_ccw_loadparm_attr.attr,
+       NULL,
+};
+
+static struct attribute_group reipl_ccw_attr_group_vm = {
+       .name  = IPL_CCW_STR,
+       .attrs = reipl_ccw_attrs_vm,
+};
+
+static struct attribute_group reipl_ccw_attr_group_lpar = {
        .name  = IPL_CCW_STR,
-       .attrs = reipl_ccw_attrs,
+       .attrs = reipl_ccw_attrs_lpar,
 };
 
 
 /* NSS reipl device attributes */
+static void reipl_get_ascii_nss_name(char *dst,
+                                    struct ipl_parameter_block *ipb)
+{
+       memcpy(dst, ipb->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
+       EBCASC(dst, NSS_NAME_SIZE);
+       dst[NSS_NAME_SIZE] = 0;
+}
+
+static ssize_t reipl_nss_name_show(struct kobject *kobj,
+                                  struct kobj_attribute *attr, char *page)
+{
+       char nss_name[NSS_NAME_SIZE + 1] = {};
 
-DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name);
+       reipl_get_ascii_nss_name(nss_name, reipl_block_nss);
+       return sprintf(page, "%s\n", nss_name);
+}
+
+static ssize_t reipl_nss_name_store(struct kobject *kobj,
+                                   struct kobj_attribute *attr,
+                                   const char *buf, size_t len)
+{
+       int nss_len;
+
+       /* ignore trailing newline */
+       nss_len = len;
+       if ((len > 0) && (buf[len - 1] == '\n'))
+               nss_len--;
+
+       if (nss_len > NSS_NAME_SIZE)
+               return -EINVAL;
+
+       memset(reipl_block_nss->ipl_info.ccw.nss_name, 0x40, NSS_NAME_SIZE);
+       if (nss_len > 0) {
+               reipl_block_nss->ipl_info.ccw.vm_flags |=
+                       DIAG308_VM_FLAGS_NSS_VALID;
+               memcpy(reipl_block_nss->ipl_info.ccw.nss_name, buf, nss_len);
+               ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
+               EBC_TOUPPER(reipl_block_nss->ipl_info.ccw.nss_name, nss_len);
+       } else {
+               reipl_block_nss->ipl_info.ccw.vm_flags &=
+                       ~DIAG308_VM_FLAGS_NSS_VALID;
+       }
+
+       return len;
+}
+
+static struct kobj_attribute sys_reipl_nss_name_attr =
+       __ATTR(name, S_IRUGO | S_IWUSR, reipl_nss_name_show,
+                                       reipl_nss_name_store);
+
+static struct kobj_attribute sys_reipl_nss_loadparm_attr =
+       __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nss_loadparm_show,
+                                           reipl_nss_loadparm_store);
 
 static struct attribute *reipl_nss_attrs[] = {
        &sys_reipl_nss_name_attr.attr,
+       &sys_reipl_nss_loadparm_attr.attr,
+       &sys_reipl_nss_vmparm_attr.attr,
        NULL,
 };
 
@@ -617,7 +848,10 @@ static int reipl_set_type(enum ipl_type type)
                reipl_method = REIPL_METHOD_FCP_DUMP;
                break;
        case IPL_TYPE_NSS:
-               reipl_method = REIPL_METHOD_NSS;
+               if (diag308_set_works)
+                       reipl_method = REIPL_METHOD_NSS_DIAG;
+               else
+                       reipl_method = REIPL_METHOD_NSS;
                break;
        case IPL_TYPE_UNKNOWN:
                reipl_method = REIPL_METHOD_DEFAULT;
@@ -655,11 +889,38 @@ static struct kobj_attribute reipl_type_attr =
 
 static struct kset *reipl_kset;
 
+static void get_ipl_string(char *dst, struct ipl_parameter_block *ipb,
+                          const enum ipl_method m)
+{
+       char loadparm[LOADPARM_LEN + 1] = {};
+       char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
+       char nss_name[NSS_NAME_SIZE + 1] = {};
+       size_t pos = 0;
+
+       reipl_get_ascii_loadparm(loadparm, ipb);
+       reipl_get_ascii_nss_name(nss_name, ipb);
+       reipl_get_ascii_vmparm(vmparm, ipb);
+
+       switch (m) {
+       case REIPL_METHOD_CCW_VM:
+               pos = sprintf(dst, "IPL %X CLEAR", ipb->ipl_info.ccw.devno);
+               break;
+       case REIPL_METHOD_NSS:
+               pos = sprintf(dst, "IPL %s", nss_name);
+               break;
+       default:
+               break;
+       }
+       if (strlen(loadparm) > 0)
+               pos += sprintf(dst + pos, " LOADPARM '%s'", loadparm);
+       if (strlen(vmparm) > 0)
+               sprintf(dst + pos, " PARM %s", vmparm);
+}
+
 static void reipl_run(struct shutdown_trigger *trigger)
 {
        struct ccw_dev_id devid;
-       static char buf[100];
-       char loadparm[LOADPARM_LEN + 1];
+       static char buf[128];
 
        switch (reipl_method) {
        case REIPL_METHOD_CCW_CIO:
@@ -668,13 +929,7 @@ static void reipl_run(struct shutdown_trigger *trigger)
                reipl_ccw_dev(&devid);
                break;
        case REIPL_METHOD_CCW_VM:
-               reipl_get_ascii_loadparm(loadparm);
-               if (strlen(loadparm) == 0)
-                       sprintf(buf, "IPL %X CLEAR",
-                               reipl_block_ccw->ipl_info.ccw.devno);
-               else
-                       sprintf(buf, "IPL %X CLEAR LOADPARM '%s'",
-                               reipl_block_ccw->ipl_info.ccw.devno, loadparm);
+               get_ipl_string(buf, reipl_block_ccw, REIPL_METHOD_CCW_VM);
                __cpcmd(buf, NULL, 0, NULL);
                break;
        case REIPL_METHOD_CCW_DIAG:
@@ -691,8 +946,12 @@ static void reipl_run(struct shutdown_trigger *trigger)
        case REIPL_METHOD_FCP_RO_VM:
                __cpcmd("IPL", NULL, 0, NULL);
                break;
+       case REIPL_METHOD_NSS_DIAG:
+               diag308(DIAG308_SET, reipl_block_nss);
+               diag308(DIAG308_IPL, NULL);
+               break;
        case REIPL_METHOD_NSS:
-               sprintf(buf, "IPL %s", reipl_nss_name);
+               get_ipl_string(buf, reipl_block_nss, REIPL_METHOD_NSS);
                __cpcmd(buf, NULL, 0, NULL);
                break;
        case REIPL_METHOD_DEFAULT:
@@ -707,16 +966,36 @@ static void reipl_run(struct shutdown_trigger *trigger)
        disabled_wait((unsigned long) __builtin_return_address(0));
 }
 
-static void __init reipl_probe(void)
+static void reipl_block_ccw_init(struct ipl_parameter_block *ipb)
 {
-       void *buffer;
+       ipb->hdr.len = IPL_PARM_BLK_CCW_LEN;
+       ipb->hdr.version = IPL_PARM_BLOCK_VERSION;
+       ipb->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
+       ipb->hdr.pbt = DIAG308_IPL_TYPE_CCW;
+}
 
-       buffer = (void *) get_zeroed_page(GFP_KERNEL);
-       if (!buffer)
-               return;
-       if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK)
-               diag308_set_works = 1;
-       free_page((unsigned long)buffer);
+static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
+{
+       /* LOADPARM */
+       /* check if read scp info worked and set loadparm */
+       if (sclp_ipl_info.is_valid)
+               memcpy(ipb->ipl_info.ccw.load_parm,
+                               &sclp_ipl_info.loadparm, LOADPARM_LEN);
+       else
+               /* read scp info failed: set empty loadparm (EBCDIC blanks) */
+               memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN);
+       ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
+
+       /* VM PARM */
+       if (MACHINE_IS_VM && diag308_set_works &&
+           (ipl_block.ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID)) {
+
+               ipb->ipl_info.ccw.vm_flags |= DIAG308_VM_FLAGS_VP_VALID;
+               ipb->ipl_info.ccw.vm_parm_len =
+                                       ipl_block.ipl_info.ccw.vm_parm_len;
+               memcpy(ipb->ipl_info.ccw.vm_parm,
+                      ipl_block.ipl_info.ccw.vm_parm, DIAG308_VMPARM_SIZE);
+       }
 }
 
 static int __init reipl_nss_init(void)
@@ -725,10 +1004,31 @@ static int __init reipl_nss_init(void)
 
        if (!MACHINE_IS_VM)
                return 0;
+
+       reipl_block_nss = (void *) get_zeroed_page(GFP_KERNEL);
+       if (!reipl_block_nss)
+               return -ENOMEM;
+
+       if (!diag308_set_works)
+               sys_reipl_nss_vmparm_attr.attr.mode = S_IRUGO;
+
        rc = sysfs_create_group(&reipl_kset->kobj, &reipl_nss_attr_group);
        if (rc)
                return rc;
-       strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
+
+       reipl_block_ccw_init(reipl_block_nss);
+       if (ipl_info.type == IPL_TYPE_NSS) {
+               memset(reipl_block_nss->ipl_info.ccw.nss_name,
+                       ' ', NSS_NAME_SIZE);
+               memcpy(reipl_block_nss->ipl_info.ccw.nss_name,
+                       kernel_nss_name, strlen(kernel_nss_name));
+               ASCEBC(reipl_block_nss->ipl_info.ccw.nss_name, NSS_NAME_SIZE);
+               reipl_block_nss->ipl_info.ccw.vm_flags |=
+                       DIAG308_VM_FLAGS_NSS_VALID;
+
+               reipl_block_ccw_fill_parms(reipl_block_nss);
+       }
+
        reipl_capabilities |= IPL_TYPE_NSS;
        return 0;
 }
@@ -740,28 +1040,27 @@ static int __init reipl_ccw_init(void)
        reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
        if (!reipl_block_ccw)
                return -ENOMEM;
-       rc = sysfs_create_group(&reipl_kset->kobj, &reipl_ccw_attr_group);
-       if (rc) {
-               free_page((unsigned long)reipl_block_ccw);
-               return rc;
+
+       if (MACHINE_IS_VM) {
+               if (!diag308_set_works)
+                       sys_reipl_ccw_vmparm_attr.attr.mode = S_IRUGO;
+               rc = sysfs_create_group(&reipl_kset->kobj,
+                                       &reipl_ccw_attr_group_vm);
+       } else {
+               if(!diag308_set_works)
+                       sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
+               rc = sysfs_create_group(&reipl_kset->kobj,
+                                       &reipl_ccw_attr_group_lpar);
        }
-       reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN;
-       reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
-       reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
-       reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
-       reipl_block_ccw->hdr.flags = DIAG308_FLAGS_LP_VALID;
-       /* check if read scp info worked and set loadparm */
-       if (sclp_ipl_info.is_valid)
-               memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
-                      &sclp_ipl_info.loadparm, LOADPARM_LEN);
-       else
-               /* read scp info failed: set empty loadparm (EBCDIC blanks) */
-               memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
-                      LOADPARM_LEN);
-       if (!MACHINE_IS_VM && !diag308_set_works)
-               sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
-       if (ipl_info.type == IPL_TYPE_CCW)
+       if (rc)
+               return rc;
+
+       reipl_block_ccw_init(reipl_block_ccw);
+       if (ipl_info.type == IPL_TYPE_CCW) {
                reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
+               reipl_block_ccw_fill_parms(reipl_block_ccw);
+       }
+
        reipl_capabilities |= IPL_TYPE_CCW;
        return 0;
 }
@@ -1298,7 +1597,6 @@ static void __init shutdown_actions_init(void)
 
 static int __init s390_ipl_init(void)
 {
-       reipl_probe();
        sclp_get_ipl_info(&sclp_ipl_info);
        shutdown_actions_init();
        shutdown_triggers_init();
@@ -1405,6 +1703,12 @@ void __init setup_ipl(void)
        atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
 }
 
+void __init ipl_update_parameters(void)
+{
+       if (diag308(DIAG308_STORE, &ipl_block) == DIAG308_RC_OK)
+               diag308_set_works = 1;
+}
+
 void __init ipl_save_parameters(void)
 {
        struct cio_iplinfo iplinfo;
index ed04d13..288ad49 100644 (file)
@@ -41,10 +41,8 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        if (is_prohibited_opcode((kprobe_opcode_t *) p->addr))
                return -EINVAL;
 
-       if ((unsigned long)p->addr & 0x01) {
-               printk("Attempt to register kprobe at an unaligned address\n");
+       if ((unsigned long)p->addr & 0x01)
                return -EINVAL;
-               }
 
        /* Use the get_insn_slot() facility for correctness */
        if (!(p->ainsn.insn = get_insn_slot()))
index 3c77dd3..131d7ee 100644 (file)
@@ -52,7 +52,6 @@ void machine_kexec_cleanup(struct kimage *image)
 
 void machine_shutdown(void)
 {
-       printk(KERN_INFO "kexec: machine_shutdown called\n");
 }
 
 void machine_kexec(struct kimage *image)
diff --git a/arch/s390/kernel/mem_detect.c b/arch/s390/kernel/mem_detect.c
new file mode 100644 (file)
index 0000000..18ed7ab
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *    Copyright IBM Corp. 2008
+ *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/ipl.h>
+#include <asm/sclp.h>
+#include <asm/setup.h>
+
+static int memory_fast_detect(struct mem_chunk *chunk)
+{
+       unsigned long val0 = 0;
+       unsigned long val1 = 0xc;
+       int rc = -EOPNOTSUPP;
+
+       if (ipl_flags & IPL_NSS_VALID)
+               return -EOPNOTSUPP;
+       asm volatile(
+               "       diag    %1,%2,0x260\n"
+               "0:     lhi     %0,0\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (rc), "+d" (val0), "+d" (val1) : : "cc");
+
+       if (rc || val0 != val1)
+               return -EOPNOTSUPP;
+       chunk->size = val0 + 1;
+       return 0;
+}
+
+static inline int tprot(unsigned long addr)
+{
+       int rc = -EFAULT;
+
+       asm volatile(
+               "       tprot   0(%1),0\n"
+               "0:     ipm     %0\n"
+               "       srl     %0,28\n"
+               "1:\n"
+               EX_TABLE(0b,1b)
+               : "+d" (rc) : "a" (addr) : "cc");
+       return rc;
+}
+
+#define ADDR2G (1ULL << 31)
+
+static void find_memory_chunks(struct mem_chunk chunk[])
+{
+       unsigned long long memsize, rnmax, rzm;
+       unsigned long addr = 0, size;
+       int i = 0, type;
+
+       rzm = sclp_get_rzm();
+       rnmax = sclp_get_rnmax();
+       memsize = rzm * rnmax;
+       if (!rzm)
+               rzm = 1ULL << 17;
+       if (sizeof(long) == 4) {
+               rzm = min(ADDR2G, rzm);
+               memsize = memsize ? min(ADDR2G, memsize) : ADDR2G;
+       }
+       do {
+               size = 0;
+               type = tprot(addr);
+               do {
+                       size += rzm;
+                       if (memsize && addr + size >= memsize)
+                               break;
+               } while (type == tprot(addr + size));
+               if (type == CHUNK_READ_WRITE || type == CHUNK_READ_ONLY) {
+                       chunk[i].addr = addr;
+                       chunk[i].size = size;
+                       chunk[i].type = type;
+                       i++;
+               }
+               addr += size;
+       } while (addr < memsize && i < MEMORY_CHUNKS);
+}
+
+void detect_memory_layout(struct mem_chunk chunk[])
+{
+       unsigned long flags, cr0;
+
+       memset(chunk, 0, MEMORY_CHUNKS * sizeof(struct mem_chunk));
+       if (memory_fast_detect(&chunk[0]) == 0)
+               return;
+       /* Disable IRQs, DAT and low address protection so tprot does the
+        * right thing and we don't get scheduled away with low address
+        * protection disabled.
+        */
+       flags = __raw_local_irq_stnsm(0xf8);
+       __ctl_store(cr0, 0, 0);
+       __ctl_clear_bit(0, 28);
+       find_memory_chunks(chunk);
+       __ctl_load(cr0, 0, 0);
+       __raw_local_irq_ssm(flags);
+}
+EXPORT_SYMBOL(detect_memory_layout);
index 7920861..85defd0 100644 (file)
@@ -75,46 +75,19 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        return sf->gprs[8];
 }
 
-/*
- * Need to know about CPUs going idle?
- */
-static ATOMIC_NOTIFIER_HEAD(idle_chain);
 DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
 
-int register_idle_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_register(&idle_chain, nb);
-}
-EXPORT_SYMBOL(register_idle_notifier);
-
-int unregister_idle_notifier(struct notifier_block *nb)
-{
-       return atomic_notifier_chain_unregister(&idle_chain, nb);
-}
-EXPORT_SYMBOL(unregister_idle_notifier);
-
 static int s390_idle_enter(void)
 {
        struct s390_idle_data *idle;
-       int nr_calls = 0;
-       void *hcpu;
-       int rc;
 
-       hcpu = (void *)(long)smp_processor_id();
-       rc = __atomic_notifier_call_chain(&idle_chain, S390_CPU_IDLE, hcpu, -1,
-                                         &nr_calls);
-       if (rc == NOTIFY_BAD) {
-               nr_calls--;
-               __atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
-                                            hcpu, nr_calls, NULL);
-               return rc;
-       }
        idle = &__get_cpu_var(s390_idle);
        spin_lock(&idle->lock);
        idle->idle_count++;
        idle->in_idle = 1;
        idle->idle_enter = get_clock();
        spin_unlock(&idle->lock);
+       vtime_stop_cpu_timer();
        return NOTIFY_OK;
 }
 
@@ -122,13 +95,12 @@ void s390_idle_leave(void)
 {
        struct s390_idle_data *idle;
 
+       vtime_start_cpu_timer();
        idle = &__get_cpu_var(s390_idle);
        spin_lock(&idle->lock);
        idle->idle_time += get_clock() - idle->idle_enter;
        idle->in_idle = 0;
        spin_unlock(&idle->lock);
-       atomic_notifier_call_chain(&idle_chain, S390_CPU_NOT_IDLE,
-                                  (void *)(long) smp_processor_id());
 }
 
 extern void s390_handle_mcck(void);
index 35827b9..2815bfe 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/security.h>
 #include <linux/audit.h>
 #include <linux/signal.h>
+#include <linux/elf.h>
+#include <linux/regset.h>
 
 #include <asm/segment.h>
 #include <asm/page.h>
 #include "compat_ptrace.h"
 #endif
 
+enum s390_regset {
+       REGSET_GENERAL,
+       REGSET_FP,
+};
+
 static void
 FixPerRegisters(struct task_struct *task)
 {
@@ -126,24 +133,10 @@ ptrace_disable(struct task_struct *child)
  * struct user contain pad bytes that should be read as zeroes.
  * Lovely...
  */
-static int
-peek_user(struct task_struct *child, addr_t addr, addr_t data)
+static unsigned long __peek_user(struct task_struct *child, addr_t addr)
 {
        struct user *dummy = NULL;
-       addr_t offset, tmp, mask;
-
-       /*
-        * Stupid gdb peeks/pokes the access registers in 64 bit with
-        * an alignment of 4. Programmers from hell...
-        */
-       mask = __ADDR_MASK;
-#ifdef CONFIG_64BIT
-       if (addr >= (addr_t) &dummy->regs.acrs &&
-           addr < (addr_t) &dummy->regs.orig_gpr2)
-               mask = 3;
-#endif
-       if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
-               return -EIO;
+       addr_t offset, tmp;
 
        if (addr < (addr_t) &dummy->regs.acrs) {
                /*
@@ -197,24 +190,18 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
        } else
                tmp = 0;
 
-       return put_user(tmp, (addr_t __user *) data);
+       return tmp;
 }
 
-/*
- * Write a word to the user area of a process at location addr. This
- * operation does have an additional problem compared to peek_user.
- * Stores to the program status word and on the floating point
- * control register needs to get checked for validity.
- */
 static int
-poke_user(struct task_struct *child, addr_t addr, addr_t data)
+peek_user(struct task_struct *child, addr_t addr, addr_t data)
 {
        struct user *dummy = NULL;
-       addr_t offset, mask;
+       addr_t tmp, mask;
 
        /*
         * Stupid gdb peeks/pokes the access registers in 64 bit with
-        * an alignment of 4. Programmers from hell indeed...
+        * an alignment of 4. Programmers from hell...
         */
        mask = __ADDR_MASK;
 #ifdef CONFIG_64BIT
@@ -225,6 +212,21 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
        if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
                return -EIO;
 
+       tmp = __peek_user(child, addr);
+       return put_user(tmp, (addr_t __user *) data);
+}
+
+/*
+ * Write a word to the user area of a process at location addr. This
+ * operation does have an additional problem compared to peek_user.
+ * Stores to the program status word and on the floating point
+ * control register needs to get checked for validity.
+ */
+static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
+{
+       struct user *dummy = NULL;
+       addr_t offset;
+
        if (addr < (addr_t) &dummy->regs.acrs) {
                /*
                 * psw and gprs are stored on the stack
@@ -292,6 +294,28 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
        return 0;
 }
 
+static int
+poke_user(struct task_struct *child, addr_t addr, addr_t data)
+{
+       struct user *dummy = NULL;
+       addr_t mask;
+
+       /*
+        * Stupid gdb peeks/pokes the access registers in 64 bit with
+        * an alignment of 4. Programmers from hell indeed...
+        */
+       mask = __ADDR_MASK;
+#ifdef CONFIG_64BIT
+       if (addr >= (addr_t) &dummy->regs.acrs &&
+           addr < (addr_t) &dummy->regs.orig_gpr2)
+               mask = 3;
+#endif
+       if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
+               return -EIO;
+
+       return __poke_user(child, addr, data);
+}
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        ptrace_area parea; 
@@ -367,18 +391,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 /*
  * Same as peek_user but for a 31 bit program.
  */
-static int
-peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
+static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
 {
        struct user32 *dummy32 = NULL;
        per_struct32 *dummy_per32 = NULL;
        addr_t offset;
        __u32 tmp;
 
-       if (!test_thread_flag(TIF_31BIT) ||
-           (addr & 3) || addr > sizeof(struct user) - 3)
-               return -EIO;
-
        if (addr < (addr_t) &dummy32->regs.acrs) {
                /*
                 * psw and gprs are stored on the stack
@@ -435,25 +454,32 @@ peek_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
        } else
                tmp = 0;
 
+       return tmp;
+}
+
+static int peek_user_compat(struct task_struct *child,
+                           addr_t addr, addr_t data)
+{
+       __u32 tmp;
+
+       if (!test_thread_flag(TIF_31BIT) ||
+           (addr & 3) || addr > sizeof(struct user) - 3)
+               return -EIO;
+
+       tmp = __peek_user_compat(child, addr);
        return put_user(tmp, (__u32 __user *) data);
 }
 
 /*
  * Same as poke_user but for a 31 bit program.
  */
-static int
-poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
+static int __poke_user_compat(struct task_struct *child,
+                             addr_t addr, addr_t data)
 {
        struct user32 *dummy32 = NULL;
        per_struct32 *dummy_per32 = NULL;
+       __u32 tmp = (__u32) data;
        addr_t offset;
-       __u32 tmp;
-
-       if (!test_thread_flag(TIF_31BIT) ||
-           (addr & 3) || addr > sizeof(struct user32) - 3)
-               return -EIO;
-
-       tmp = (__u32) data;
 
        if (addr < (addr_t) &dummy32->regs.acrs) {
                /*
@@ -528,6 +554,16 @@ poke_user_emu31(struct task_struct *child, addr_t addr, addr_t data)
        return 0;
 }
 
+static int poke_user_compat(struct task_struct *child,
+                           addr_t addr, addr_t data)
+{
+       if (!test_thread_flag(TIF_31BIT) ||
+           (addr & 3) || addr > sizeof(struct user32) - 3)
+               return -EIO;
+
+       return __poke_user_compat(child, addr, data);
+}
+
 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        compat_ulong_t caddr, compat_ulong_t cdata)
 {
@@ -539,11 +575,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
        switch (request) {
        case PTRACE_PEEKUSR:
                /* read the word at location addr in the USER area. */
-               return peek_user_emu31(child, addr, data);
+               return peek_user_compat(child, addr, data);
 
        case PTRACE_POKEUSR:
                /* write the word at location addr in the USER area */
-               return poke_user_emu31(child, addr, data);
+               return poke_user_compat(child, addr, data);
 
        case PTRACE_PEEKUSR_AREA:
        case PTRACE_POKEUSR_AREA:
@@ -555,13 +591,13 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                copied = 0;
                while (copied < parea.len) {
                        if (request == PTRACE_PEEKUSR_AREA)
-                               ret = peek_user_emu31(child, addr, data);
+                               ret = peek_user_compat(child, addr, data);
                        else {
                                __u32 utmp;
                                if (get_user(utmp,
                                             (__u32 __force __user *) data))
                                        return -EFAULT;
-                               ret = poke_user_emu31(child, addr, utmp);
+                               ret = poke_user_compat(child, addr, utmp);
                        }
                        if (ret)
                                return ret;
@@ -610,3 +646,240 @@ syscall_trace(struct pt_regs *regs, int entryexit)
                                    regs->gprs[2], regs->orig_gpr2, regs->gprs[3],
                                    regs->gprs[4], regs->gprs[5]);
 }
+
+/*
+ * user_regset definitions.
+ */
+
+static int s390_regs_get(struct task_struct *target,
+                        const struct user_regset *regset,
+                        unsigned int pos, unsigned int count,
+                        void *kbuf, void __user *ubuf)
+{
+       if (target == current)
+               save_access_regs(target->thread.acrs);
+
+       if (kbuf) {
+               unsigned long *k = kbuf;
+               while (count > 0) {
+                       *k++ = __peek_user(target, pos);
+                       count -= sizeof(*k);
+                       pos += sizeof(*k);
+               }
+       } else {
+               unsigned long __user *u = ubuf;
+               while (count > 0) {
+                       if (__put_user(__peek_user(target, pos), u++))
+                               return -EFAULT;
+                       count -= sizeof(*u);
+                       pos += sizeof(*u);
+               }
+       }
+       return 0;
+}
+
+static int s390_regs_set(struct task_struct *target,
+                        const struct user_regset *regset,
+                        unsigned int pos, unsigned int count,
+                        const void *kbuf, const void __user *ubuf)
+{
+       int rc = 0;
+
+       if (target == current)
+               save_access_regs(target->thread.acrs);
+
+       if (kbuf) {
+               const unsigned long *k = kbuf;
+               while (count > 0 && !rc) {
+                       rc = __poke_user(target, pos, *k++);
+                       count -= sizeof(*k);
+                       pos += sizeof(*k);
+               }
+       } else {
+               const unsigned long  __user *u = ubuf;
+               while (count > 0 && !rc) {
+                       unsigned long word;
+                       rc = __get_user(word, u++);
+                       if (rc)
+                               break;
+                       rc = __poke_user(target, pos, word);
+                       count -= sizeof(*u);
+                       pos += sizeof(*u);
+               }
+       }
+
+       if (rc == 0 && target == current)
+               restore_access_regs(target->thread.acrs);
+
+       return rc;
+}
+
+static int s390_fpregs_get(struct task_struct *target,
+                          const struct user_regset *regset, unsigned int pos,
+                          unsigned int count, void *kbuf, void __user *ubuf)
+{
+       if (target == current)
+               save_fp_regs(&target->thread.fp_regs);
+
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                  &target->thread.fp_regs, 0, -1);
+}
+
+static int s390_fpregs_set(struct task_struct *target,
+                          const struct user_regset *regset, unsigned int pos,
+                          unsigned int count, const void *kbuf,
+                          const void __user *ubuf)
+{
+       int rc = 0;
+
+       if (target == current)
+               save_fp_regs(&target->thread.fp_regs);
+
+   &nb